From f9db9fd7343aa0b8a77b90565f07f14c4b0740a5 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Mon, 29 Sep 2025 16:50:40 -0700 Subject: [PATCH 01/71] 1) new constraint schema, 2) resturcture well jac assem loops --- .../physicsSolvers/fluidFlow/CMakeLists.txt | 14 + .../fluidFlow/wells/WellBHPConstraints.cpp | 113 ++++ .../fluidFlow/wells/WellBHPConstraints.hpp | 341 +++++++++++ .../fluidFlow/wells/WellConstraintsBase.cpp | 137 +++++ .../fluidFlow/wells/WellConstraintsBase.hpp | 422 +++++++++++++ .../fluidFlow/wells/WellControls.cpp | 168 +++++- .../fluidFlow/wells/WellControls.hpp | 101 +++- .../wells/WellLiquidRateConstraints.cpp | 85 +++ .../wells/WellLiquidRateConstraints.hpp | 242 ++++++++ .../wells/WellMassRateConstraints.cpp | 109 ++++ .../wells/WellMassRateConstraints.hpp | 273 +++++++++ .../wells/WellPhaseRateConstraints.cpp | 126 ++++ .../wells/WellPhaseRateConstraints.hpp | 354 +++++++++++ .../wells/WellTotalVolRateConstraints.cpp | 107 ++++ .../wells/WellTotalVolRateConstraints.hpp | 286 +++++++++ .../CompositionalMultiphaseWellKernels.cpp | 37 +- .../CompositionalMultiphaseWellKernels.hpp | 2 +- .../wells/kernels/WellConstraintKernels.hpp | 568 ++++++++++++++++++ src/coreComponents/schema/schema.xsd | 4 + 19 files changed, 3466 insertions(+), 23 deletions(-) create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.cpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.cpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.cpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.cpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.cpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/WellConstraintKernels.hpp diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt index 28ffa57e587..11818d57fc8 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt +++ b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt @@ -116,11 +116,19 @@ set( fluidFlowSolvers_headers wells/SinglePhaseWellFields.hpp wells/WellConstants.hpp wells/WellControls.hpp + wells/WellConstraintsBase.hpp + wells/WellBHPConstraints.hpp + wells/WellTotalVolRateConstraints.hpp + wells/WellMassRateConstraints.hpp + wells/WellPhaseRateConstraints.hpp + wells/WellLiquidRateConstraints.hpp wells/WellSolverBase.hpp wells/WellSolverBaseFields.hpp wells/LogLevelsInfo.hpp wells/kernels/SinglePhaseWellKernels.hpp wells/kernels/CompositionalMultiphaseWellKernels.hpp + wells/kernels/WellConstraintKernels.hpp + proppantTransport/ProppantTransport.hpp proppantTransport/ProppantTransportFields.hpp proppantTransport/ProppantTransportKernels.hpp ) @@ -150,6 +158,12 @@ set( fluidFlowSolvers_sources wells/SinglePhaseWell.cpp wells/kernels/SinglePhaseWellKernels.cpp wells/WellControls.cpp + wells/WellConstraintsBase.cpp + wells/WellBHPConstraints.cpp + wells/WellTotalVolRateConstraints.cpp + wells/WellMassRateConstraints.cpp + wells/WellPhaseRateConstraints.cpp + wells/WellLiquidRateConstraints.cpp wells/WellSolverBase.cpp proppantTransport/ProppantTransport.cpp proppantTransport/ProppantTransportKernels.cpp ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.cpp new file mode 100644 index 00000000000..8577c299a0e --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.cpp @@ -0,0 +1,113 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellConstraint.cpp + */ + +#include "LogLevelsInfo.hpp" +#include "WellBHPConstraints.hpp" +#include "WellConstants.hpp" +#include "dataRepository/InputFlags.hpp" +#include "functions/FunctionManager.hpp" + + +namespace geos +{ + +using namespace dataRepository; + +BHPConstraint::BHPConstraint( string const & name, Group * const parent ) + : WellConstraintBase( name, parent ), + m_refElevation( 0.0 ), + m_refGravCoef( 0.0 ) +{ + setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); + + registerWrapper( viewKeyStruct::targetBHPString(), &m_constraintValue ). + setDefaultValue( 0.0 ). + setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). + setDescription( "Minimun bottom-hole production pressure [Pa]" ); + + registerWrapper( viewKeyStruct::refElevString(), &m_refElevation ). + setDefaultValue( -1 ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Reference elevation where BHP control is enforced [m]" ); + +} + + +BHPConstraint::~BHPConstraint() +{} + +void BHPConstraint::postInputInitialization() +{ + + WellConstraintBase::postInputInitialization(); + +} + +MinimumBHPConstraint::MinimumBHPConstraint( string const & name, Group * const parent ) + : BHPConstraint( name, parent ) +{ + setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); + + registerWrapper( viewKeyStruct::targetBHPString(), &m_constraintValue ). + setDefaultValue( 0.0 ). + setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). + setDescription( "Minimun bottom-hole production pressure [Pa]" ); +} + + +MinimumBHPConstraint::~MinimumBHPConstraint() +{} + +void MinimumBHPConstraint::postInputInitialization() +{ + + BHPConstraint::postInputInitialization(); + +} + +bool MinimumBHPConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const +{ + return currentConstraint.bottomHolePressure() < getConstraintValue( currentTime ); +} + +MaximumBHPConstraint::MaximumBHPConstraint( string const & name, Group * const parent ) + : BHPConstraint( name, parent ) +{ + setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); + +} + + +MaximumBHPConstraint::~MaximumBHPConstraint() +{} + +void MaximumBHPConstraint::postInputInitialization() +{ + // Validate value and table options + BHPConstraint::postInputInitialization(); + +} +bool MaximumBHPConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const +{ + return currentConstraint.bottomHolePressure() > getConstraintValue( currentTime ); +} + +} //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp new file mode 100644 index 00000000000..09c80d17c36 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp @@ -0,0 +1,341 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellControls.hpp + */ + + +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLBHPCONSTRAINTS_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLBHPCONSTRAINTS_HPP + +#include "common/format/EnumStrings.hpp" +#include "dataRepository/Group.hpp" +#include "functions/TableFunction.hpp" +#include "WellConstraintsBase.hpp" +namespace geos +{ + +/** + * @class BHPConstraint + * @brief This class describes a minimum pressure constraint used to control a injection well. + */ +class BHPConstraint : public WellConstraintBase +{ +public: + + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for WellControls Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit BHPConstraint( string const & name, dataRepository::Group * const parent ); + + + /** + * @brief Default destructor. + */ + ~BHPConstraint() override; + + /** + * @brief Deleted default constructor. + */ + BHPConstraint() = delete; + + /** + * @brief Deleted copy constructor. + */ + BHPConstraint( BHPConstraint const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + BHPConstraint( BHPConstraint && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + BHPConstraint & operator=( BHPConstraint const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + BHPConstraint & operator=( BHPConstraint && ) = delete; + + ///@} + + + /** + * @name Getters / Setters + */ + ///@{ + + // Temp interface - tjb + virtual ConstraintTypeId getControl() const override { return ConstraintTypeId::BHP; }; + + /** + * @name Getters / Setters + */ + ///@{ + /** + * @brief Get name of constraint + * @return constraint key + */ + virtual std::string getConstraintKey( ) const override { return "BHPConstraint"; }; + ///@} + + ///@} + /** + * @brief Struct to serve as a container for variable strings and keys. + * @struct viewKeyStruct + */ + struct viewKeyStruct + { + /// String key for the well target BHP + static constexpr char const * targetBHPString() { return "targetBHP"; } + /// String key for the well reference elevation (for BHP control) + static constexpr char const * refElevString() { return "referenceElevation"; } + } + viewKeysWellBHPConstraint; + + //virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const override; + + /** + * @brief Getter for the reference elevation where the BHP control is enforced + * @return the reference elevation + */ + real64 getReferenceElevation() const { return m_refElevation; } + + /** + * @brief Set the reference elevation where the BHP control is enforced + * @return the reference elevation + */ + void setReferenceElevation( real64 const & refElevation ) { m_refElevation=refElevation; } + + /** + * @brief Getter for the reference gravity coefficient + * @return the reference gravity coefficient + */ + real64 getReferenceGravityCoef() const { return m_refGravCoef; } + + /** + * @brief Setter for the reference gravity + */ + void setReferenceGravityCoef( real64 const & refGravCoef ) { m_refGravCoef = refGravCoef; } + +protected: + + virtual void postInputInitialization() override; + + /// Reference elevation + real64 m_refElevation; + + /// Gravity coefficient of the reference elevation + real64 m_refGravCoef; + +}; + +/** + * @class MinimumBHPConstraint + * @brief This class describes a minimum pressure constraint used to control a injection well. + */ +class MinimumBHPConstraint : public BHPConstraint +{ +public: + + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for WellControls Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit MinimumBHPConstraint( string const & name, dataRepository::Group * const parent ); + + + /** + * @brief Default destructor. + */ + ~MinimumBHPConstraint() override; + + /** + * @brief Deleted default constructor. + */ + MinimumBHPConstraint() = delete; + + /** + * @brief Deleted copy constructor. + */ + MinimumBHPConstraint( MinimumBHPConstraint const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + MinimumBHPConstraint( MinimumBHPConstraint && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + MinimumBHPConstraint & operator=( MinimumBHPConstraint const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + MinimumBHPConstraint & operator=( MinimumBHPConstraint && ) = delete; + + ///@} + + + /** + * @name Getters / Setters + */ + ///@{ + + // Temp interface - tjb + virtual ConstraintTypeId getControl() const override { return ConstraintTypeId::BHP; }; + /** + * @brief Get name of constraint + * @return constraint key + */ + virtual std::string getConstraintKey( ) const override { return "MinimumBHPConstraint"; }; + ///@} + /** + * @brief Struct to serve as a container for variable strings and keys. + * @struct viewKeyStruct + */ + struct viewKeyStruct + { + /// String key for the well target BHP + static constexpr char const * targetBHPString() { return "targetBHP"; } + } + viewKeysWellBHPConstraint; + + virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const override; + +protected: + + virtual void postInputInitialization() override; + + +}; + +/** + * @class WellMinimumBHPConstraint + * @brief This class describes a maximum pressure constraint used to control a injection well. + */ +class MaximumBHPConstraint : public BHPConstraint +{ +public: + + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for WellControls Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit MaximumBHPConstraint( string const & name, dataRepository::Group * const parent ); + + + /** + * @brief Default destructor. + */ + ~MaximumBHPConstraint() override; + + /** + * @brief Deleted default constructor. + */ + MaximumBHPConstraint() = delete; + + /** + * @brief Deleted copy constructor. + */ + MaximumBHPConstraint( MaximumBHPConstraint const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + MaximumBHPConstraint( MaximumBHPConstraint && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + MaximumBHPConstraint & operator=( MaximumBHPConstraint const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + MaximumBHPConstraint & operator=( MaximumBHPConstraint && ) = delete; + + ///@} + + + /** + * @name Getters / Setters + */ + ///@{ + // Temp interface - tjb + virtual ConstraintTypeId getControl() const override { return ConstraintTypeId::BHP; }; + /** + * @brief Get name of constraint + * @return constraint key + */ + virtual std::string getConstraintKey( ) const override { return "MaximumBHPConstraint"; }; + + ///@} + /** + * @brief Struct to serve as a container for variable strings and keys. + * @struct viewKeyStruct + */ + struct viewKeyStruct + { + /// String key for the well target BHP + static constexpr char const * targetBHPString() { return "targetBHP"; } + } + viewKeysWellBHPConstraint; + + virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const override; +protected: + + virtual void postInputInitialization() override; + + + +private: + + +}; + + +} //namespace geos + +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLBHPCONSTRAINTS_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp new file mode 100644 index 00000000000..9fcc01525c3 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp @@ -0,0 +1,137 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellConstraintBase.cpp + */ + +#include "LogLevelsInfo.hpp" +#include "WellConstraintsBase.hpp" +#include "WellConstants.hpp" +#include "dataRepository/InputFlags.hpp" +#include "functions/FunctionManager.hpp" + + +namespace geos +{ + +using namespace dataRepository; + +namespace +{ + + +#if 0 +/// Utility function to create a one-value table internally when not provided by the user +TableFunction * createConstraintScheduleTable( string const & tableName, + real64 const & constantValue ) +{ + array1d< array1d< real64 > > timeCoord; + timeCoord.resize( 1 ); + timeCoord[0].emplace_back( 0 ); + array1d< real64 > constantValueArray; + constantValueArray.emplace_back( constantValue ); + + FunctionManager & functionManager = FunctionManager::getInstance(); + TableFunction * table = dynamicCast< TableFunction * >( functionManager.createChild( TableFunction::catalogName(), tableName )); + table->setTableCoordinates( timeCoord, { units::Time } ); + table->setTableValues( constantValueArray ); + table->setInterpolationMethod( TableFunction::InterpolationType::Lower ); + return table; +} +#endif + + +} + +WellConstraintBase::WellConstraintBase( string const & name, Group * const parent ) + : Group( name, parent ), + m_isConstraintActive( true ), + m_useScheduleTable( false ), + m_constraintValue( 0 ), + m_constraintScheduleTable( nullptr ), + m_rateSign( 1.0 ) // Default to positive rate sign for injection, set to -1.0 for production wells + +{ + setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); + + registerWrapper( viewKeyStruct::constraintScheduleTableNameString(), &m_constraintScheduleTableName ). + setRTTypeName( rtTypes::CustomTypes::groupNameRef ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Name of the well constraint schedule table when the constraint value is a time dependent function. \n" ); + +} + + +WellConstraintBase::~WellConstraintBase() +{} + + +void WellConstraintBase::postInputInitialization() +{ + + // check constraint value + GEOS_THROW_IF( m_constraintValue < 0, + getWrapperDataContext( constraintViewStruct::constraintValueKey::constraintValueString() ) << ": Target value is negative", + InputError ); + + + GEOS_THROW_IF( ((m_constraintValue > 0.0 && !m_constraintScheduleTableName.empty())), + getConstraintKey() << " " << getDataContext() << ": You have provided redundant information for well constraint value ." << + " A constraint value and table of constraint values cannot be specified together", + InputError ); + + // Create time-dependent constraint table + if( !m_constraintScheduleTableName.empty() ) + { + FunctionManager & functionManager = FunctionManager::getInstance(); + m_constraintScheduleTable = &(functionManager.getGroup< TableFunction const >( m_constraintScheduleTableName )); + + GEOS_THROW_IF( m_constraintScheduleTable->getInterpolationMethod() != TableFunction::InterpolationType::Lower, + getConstraintKey() << " " << getDataContext() << ": The interpolation method for the schedule table " + << m_constraintScheduleTable->getName() << " should be TableFunction::InterpolationType::Lower", + InputError ); + } + + + GEOS_THROW_IF ((m_constraintValue <= 0.0 && m_constraintScheduleTableName.empty()), + getConstraintKey() << " " << getDataContext() << ": You need to specify a volume rate constraint. \n" << + "The rate constraint can be specified using " << + "either " << constraintViewStruct::constraintValueKey::constraintValueString() << + " or " << constraintViewStruct::constraintValueKey::constraintScheduleTableNameString(), + InputError ); + +} + +void WellConstraintBase::setNextDtFromTables( real64 const currentTime, real64 & nextDt ) +{ + setNextDtFromTable( m_constraintScheduleTable, currentTime, nextDt ); +} + +void WellConstraintBase::setNextDtFromTable( TableFunction const * table, real64 const currentTime, real64 & nextDt ) +{ + if( table ) + { + // small epsilon to make sure we land on the other side of table interval and pick up the right rate + real64 const eps = 1e-6; + real64 const dtLimit = (table->getCoord( ¤tTime, 0, TableFunction::InterpolationType::Upper ) - currentTime) * ( 1.0 + eps ); + if( dtLimit > eps && dtLimit < nextDt ) + { + nextDt = dtLimit; + } + } +} + +} //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp new file mode 100644 index 00000000000..51527811935 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp @@ -0,0 +1,422 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellControls.hpp + */ + + +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINT_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINT_HPP + +#include "common/format/EnumStrings.hpp" +#include "dataRepository/Group.hpp" +#include "functions/TableFunction.hpp" + +namespace geos +{ +namespace dataRepository +{ +namespace keys +{ +static constexpr auto wellConstraintBase = "WellConstraintBase"; +} +} + +namespace constraintViewStruct +{ + +struct constraintValueKey +{ + /// String key for the well constraint value + static constexpr char const * constraintValueString() { return "constraintValue"; } + /// string key for constraint values entered table name + static constexpr char const * constraintScheduleTableNameString() { return "constraintScheduleTableName"; } +}; + +struct surfaceConditionsKey +{ + /// String key for checking the rates at surface conditions + static constexpr char const * useSurfaceConditionsString() { return "useSurfaceConditions"; } + /// String key for the surface pressure + static constexpr char const * surfacePressureString() { return "surfacePressure"; } + /// String key for the surface temperature + static constexpr char const * surfaceTemperatureString() { return "surfaceTemperature"; } +}; + +struct injectionStreamKey +{ + /// String key for the well injection stream + static constexpr char const * injectionStreamString() { return "injectionStream"; } + /// String key for the well injection temperature + static constexpr char const * injectionTemperatureString() { return "injectionTemperature"; } +}; + +} +/** + * @brief Register fields required to define surface conditions for constraint + * @param[in] useSurfaceConditions 0 - use reservoir conditions, 1 use specified P & T + * @param[in] surfacePres surface pressure + * @param[in] surfaceTemp surface pressure + */ +template< typename T > +void registerSurfaceConditions( integer & useSurfaceConditions, + real64 & surfacePres, + real64 & surfaceTemp, + T & context ) +{ + context.registerWrapper( constraintViewStruct::surfaceConditionsKey::useSurfaceConditionsString(), &useSurfaceConditions ). + setDefaultValue( 0 ). + setInputFlag( dataRepository::InputFlags::OPTIONAL ). + setDescription( "Flag to specify whether rates are checked at surface or reservoir conditions.\n" + "Equal to 1 for surface conditions, and to 0 for reservoir conditions" ); + + context.registerWrapper( constraintViewStruct::surfaceConditionsKey::surfacePressureString(), &surfacePres ). + setDefaultValue( 0 ). + setInputFlag( dataRepository::InputFlags::OPTIONAL ). + setDescription( "Surface pressure used to compute volumetric rates when surface conditions are used [Pa]" ); + + context.registerWrapper( constraintViewStruct::surfaceConditionsKey::surfaceTemperatureString(), &surfaceTemp ). + setDefaultValue( 0 ). + setInputFlag( dataRepository::InputFlags::OPTIONAL ). + setDescription( "Surface temperature used to compute volumetric rates when surface conditions are used [K]" ); +} + +/** + * @brief Register fields required to define an injection stream. + * @param[in] injectionStream the injection stream vector + * @param[in] injectionTemperature the injection temperature + * @param[in] context class needing fields + */ +template< typename T > +void registerInjectionStream( array1d< real64 > & injectionStream, + real64 & injectionTemperature, + T & context ) +{ + context.registerWrapper( constraintViewStruct::injectionStreamKey::injectionStreamString(), &injectionStream ). + setDefaultValue( -1 ). + setSizedFromParent( 0 ). + setInputFlag( dataRepository::InputFlags::OPTIONAL ). + setDescription( "Global component densities of the injection stream [moles/m^3 or kg/m^3]" ); + + context.registerWrapper( constraintViewStruct::injectionStreamKey::injectionTemperatureString(), &injectionTemperature ). + setDefaultValue( -1 ). + setInputFlag( dataRepository::InputFlags::OPTIONAL ). + setDescription( "Temperature of the injection stream [K]" ); +} +/** + * @brief Validate the surface conditions + * @param[in] useSurfaceConditions 0 - use reservoir conditions, 1 use specified P & T + * @param[in] className owner of fields + * @param[in] dataContext context for error messages + */ +template< typename T > +void validateSurfaceConditions( integer useSurfaceConditions, + std::string const & className, + T const & context ) +{ + GEOS_THROW_IF( useSurfaceConditions != 0 && useSurfaceConditions != 1, + className << " " << context.getDataContext() << ": The flag to select surface/reservoir conditions must be equal to 0 or 1", + InputError ); +} + + +/** + * @brief Validate the injection stream and temperature. + * @param[in] injectionStream the injection stream vector + * @param[in] injectionTemperature the injection temperature + * @param[in] dataContext context for error messages + */ +template< typename T > +void validateInjectionStream( array1d< real64 > const & injectionStream, + real64 const & injectionTemperature, + std::string const & className, + T const & context ) +{ + GEOS_THROW_IF( (injectionStream.empty() && injectionTemperature >= 0) || + (!injectionStream.empty() && injectionTemperature < 0), + className << " " << context.getDataContext() << ": Both " + << constraintViewStruct::injectionStreamKey::injectionStreamString() << " and " << constraintViewStruct::injectionStreamKey::injectionTemperatureString() + << " must be specified for multiphase simulations", + InputError ); + + if( !injectionStream.empty()) + { + real64 sum = 0.0; + for( localIndex ic = 0; ic < injectionStream.size(); ++ic ) + { + GEOS_ERROR_IF( injectionStream[ic] < 0.0 || injectionStream[ic] > 1.0, + context.getWrapperDataContext( constraintViewStruct::injectionStreamKey::injectionStreamString() ) << ": Invalid injection stream" ); + sum += injectionStream[ic]; + } + GEOS_THROW_IF( LvArray::math::abs( 1.0 - sum ) > std::numeric_limits< real64 >::epsilon(), + context.getWrapperDataContext( constraintViewStruct::injectionStreamKey::injectionStreamString() ) << ": Invalid injection stream", + InputError ); + } +} + + +enum class ConstraintTypeId : integer +{ + BHP, /**< The well operates at a specified bottom hole pressure (BHP) */ + PHASEVOLRATE, /**< The well operates at a specified phase volumetric flow rate */ + TOTALVOLRATE, /**< The well operates at a specified total volumetric flow rate */ + MASSRATE, /**evaluate( ¤tTime ); + } + + ///@} + + // Phase constraint defintion keys + constraintViewStruct::constraintValueKey viewKeysConstraintValue; + + /** + * @brief Struct to serve as a container for variable strings and keys. + * @struct viewKeyStruct + */ + struct viewKeyStruct + { + /// string key for schedule table name + static constexpr char const * constraintScheduleTableNameString() { return "constraintScheduleTableName"; } + + } + /// ViewKey struct for the WellControls class + viewKeysWellConstraint; + + // Quantities computed from well constraint solve with this boundary condition + // This needs to be somewhere else tjb + void setBHP( real64 bhp ){ m_BHP=bhp;}; + void setPhaseVolumeRates( array1d< real64 > const & phaseVolumeRates ) { m_phaseVolumeRates = phaseVolumeRates; }; + void setTotalVolumeRate( real64 totalVolumeRate ){ m_totalVolumeRate = totalVolumeRate; }; + void setMassRate( real64 massRate ){ m_massRate = massRate; }; + + /** + * @brief Getter for the bottom hole pressure + * @return bottom hole pressure + */ + real64 bottomHolePressure() const { return m_BHP; } + + /** + * @brief Getter for the phase volume rates + * @return an arrayView1d storing the phase volume rates + */ + arrayView1d< real64 const > phaseVolumeRates() const { return m_phaseVolumeRates; } + + /** + * @brief Getter for the total volume rate + * @return mass rate + */ + real64 totalVolumeRate() const { return m_totalVolumeRate; } + + /** + * @brief Getter for the liquid rate + * @return liquid rate + */ + real64 liquidRate() const { return m_liquidRate; } + + /** + * @brief Getter for the mass rate + * @return mass rate + */ + real64 massRate() const { return m_massRate; } + + // endof This needs to be somewhere else tjb + /** + * @brief Check if this constraint is violated + * @return true if limiting constraint, false otherwise + */ + virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const = 0; + +protected: + + virtual void postInputInitialization() override; + + /** + * @brief set next time step based on tables intervals + * @param[in] currentTime the current time + * @param[inout] nextDt the time step + */ + void setNextDtFromTables( real64 const currentTime, real64 & nextDt ); + + +protected: + + /// Constraint status + bool m_isConstraintActive; + + /// Flag to indicate whether a schedule table should be generated for constraint value; + bool m_useScheduleTable; + + /// Constraint value + real64 m_constraintValue; + + void setNextDtFromTable( TableFunction const * table, real64 const currentTime, real64 & nextDt ); + + /// Constraint schedule table name + string m_constraintScheduleTableName; + + /// Constraint values versus time + TableFunction const * m_constraintScheduleTable; + + // Quantities computed from well constraint solve with this boundary condition + + // botton hole pressure + real64 m_BHP; + + // phase rates + array1d< real64 > m_phaseVolumeRates; + + // liquid rate + real64 m_liquidRate; + + // total volume rate + real64 m_totalVolumeRate; + + // mass rate + real64 m_massRate; + + /// Rate sign. +1 for injector, -1 for producer + real64 m_rateSign; +}; + + + +} //namespace geos + +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINT_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index 15914dfb8a1..8c28ad66832 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -32,24 +32,28 @@ using namespace dataRepository; WellControls::WellControls( string const & name, Group * const parent ) : Group( name, parent ), m_type( Type::PRODUCER ), - m_refElevation( 0.0 ), - m_refGravCoef( 0.0 ), - m_inputControl( Control::UNINITIALIZED ), - m_currentControl( Control::UNINITIALIZED ), + m_refElevation( 0.0 ), // tjb remove + m_refGravCoef( 0.0 ), // tjb remove + m_inputControl( Control::UNINITIALIZED ), // tjb remove + m_currentControl( Control::UNINITIALIZED ), // tjb remove m_targetBHP( 0.0 ), - m_targetTotalRate( 0.0 ), - m_targetPhaseRate( 0.0 ), - m_targetMassRate( 0.0 ), + m_targetTotalRate( 0.0 ), // tjb remove + m_targetPhaseRate( 0.0 ), // tjb remove + m_targetMassRate( 0.0 ), // tjb remove m_useSurfaceConditions( 0 ), - m_surfacePres( 0.0 ), - m_surfaceTemp( 0.0 ), + m_surfacePres( -1.0 ), + m_surfaceTemp( -1.0 ), m_isCrossflowEnabled( 1 ), m_initialPressureCoefficient( 0.1 ), m_rateSign( -1.0 ), - m_targetTotalRateTable( nullptr ), - m_targetPhaseRateTable( nullptr ), - m_targetBHPTable( nullptr ), + m_targetTotalRateTable( nullptr ), // tjb remove + m_targetPhaseRateTable( nullptr ), // tjb remove + m_targetBHPTable( nullptr ), // tjb remove m_statusTable( nullptr ), + m_wellOpen( false ), + m_estimateSolution( 0 ), + m_constraintSwitch( true ), + m_currentConstraint( nullptr ), m_wellStatus( WellControls::Status::OPEN ), m_regionAveragePressure( -1 ) { @@ -180,6 +184,12 @@ WellControls::WellControls( string const & name, Group * const parent ) setDescription( "Name of the well status table when the status of the well is a time dependent function. \n" "If the status function evaluates to a positive value at the current time, the well will be open otherwise the well will be shut." ); + + this->registerWrapper( viewKeyStruct::estimateWellSolutionString(), &m_estimateSolution ). + setApplyDefaultValue( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Flag to esitmate well solution prior to coupled reservoir and well solve." ); + addLogLevel< logInfo::WellControl >(); } @@ -187,6 +197,109 @@ WellControls::WellControls( string const & name, Group * const parent ) WellControls::~WellControls() {} +Group * WellControls::createChild( string const & childKey, string const & childName ) +{ + GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); + ////const auto childTypes = { viewKeyStruct::perforationString() }; + //GEOS_ERROR_IF( childKey != viewKeyStruct::perforationString(), + // CatalogInterface::unknownTypeError( childKey, getDataContext(), childTypes ) ); + + Group * constraint = nullptr; + if( childKey == viewKeyStruct::minimumWHPConstraintString() ) + { + MinimumWHPConstraint & whpConstraint = registerGroup< MinimumWHPConstraint >( childName ); + m_minWHPConstraint = std::shared_ptr< MinimumWHPConstraint >( &whpConstraint ); + constraint = &whpConstraint; + } + else if( childKey == viewKeyStruct::minimumBHPConstraintString() ) + { + MinimumBHPConstraint & bhpConstraint = registerGroup< MinimumBHPConstraint >( childName ); + m_minBHPConstraint = std::shared_ptr< MinimumBHPConstraint >( &bhpConstraint ); + constraint = &bhpConstraint; + } + else if( childKey == viewKeyStruct::maximumBHPConstraintString() ) + { + MaximumBHPConstraint & bhpConstraint = registerGroup< MaximumBHPConstraint >( childName ); + m_maxBHPConstraint = std::shared_ptr< MaximumBHPConstraint >( &bhpConstraint ); + constraint = &bhpConstraint; + } + else if( childKey == viewKeyStruct::phaseProductionConstraintString() ) + { + PhaseProductionConstraint & phaseConstraint = registerGroup< PhaseProductionConstraint >( childName ); + m_productionRateConstraintList.emplace_back( std::shared_ptr< WellConstraintBase >( &phaseConstraint ) ); + constraint = &phaseConstraint; + } + else if( childKey == viewKeyStruct::phaseInjectionConstraintString() ) + { + PhaseInjectionConstraint & phaseConstraint = registerGroup< PhaseInjectionConstraint >( childName ); + m_injectionRateConstraintList.emplace_back( std::shared_ptr< WellConstraintBase >( &phaseConstraint ) ); + constraint = &phaseConstraint; + } + else if( childKey == viewKeyStruct::totalVolProductionConstraintString() ) + { + TotalVolProductionConstraint & volConstraint = registerGroup< TotalVolProductionConstraint >( childName ); + m_productionRateConstraintList.emplace_back( std::shared_ptr< WellConstraintBase >( &volConstraint ) ); + constraint = &volConstraint; + } + else if( childKey == viewKeyStruct::totalVolInjectionConstraintString() ) + { + TotalVolInjectionConstraint & volConstraint = registerGroup< TotalVolInjectionConstraint >( childName ); + m_injectionRateConstraintList.emplace_back( std::shared_ptr< WellConstraintBase >( &volConstraint ) ); + constraint = &volConstraint; + } + else if( childKey == viewKeyStruct::massProductionConstraintString() ) + { + MassProductionConstraint & massConstraint = registerGroup< MassProductionConstraint >( childName ); + m_productionRateConstraintList.emplace_back( std::shared_ptr< WellConstraintBase >( &massConstraint ) ); + constraint = &massConstraint; + + } + else if( childKey == viewKeyStruct::massInjectionConstraintString() ) + { + MassInjectionConstraint & massConstraint = registerGroup< MassInjectionConstraint >( childName ); + m_injectionRateConstraintList.emplace_back( std::shared_ptr< WellConstraintBase >( &massConstraint ) ); + constraint = &massConstraint; + } + else if( childKey == viewKeyStruct::liquidProductionConstraintString() ) + { + LiquidProductionConstraint & liquidConstraint = registerGroup< LiquidProductionConstraint >( childName ); + m_productionRateConstraintList.emplace_back( std::shared_ptr< LiquidProductionConstraint >( &liquidConstraint ) ); + constraint = &liquidConstraint; + } + return constraint; +} + +void WellControls::createMinBHPConstraintForWHP() +{ + // Create constraint and set local pointer + MinimumBHPConstraint & bhpConstraint = registerGroup< MinimumBHPConstraint >( m_minWHPConstraint->getName()+"MinimumBHPConstraint" ); + m_minBHPConstraintForWHP = std::shared_ptr< MinimumBHPConstraint >( &bhpConstraint ); + // Set properties from the original minBHP constraint + m_minBHPConstraintForWHP->setReferenceElevation( m_minBHPConstraint->getReferenceElevation() ); + m_minBHPConstraintForWHP->setReferenceGravityCoef ( m_minBHPConstraint->getReferenceGravityCoef() ); + // Set to inactive. WHP estimator solve will set status + m_minBHPConstraintForWHP->setConstraintActive( false ); +} +void WellControls::createMaxLiquidConstraintForWHP() +{ + // Create constraint and set local pointer + LiquidProductionConstraint & liquidConstraint = registerGroup< LiquidProductionConstraint >( m_minWHPConstraint->getName()+"LiquidProductionConstraint" ); + m_maxLiquidConstraintForWHP = std::shared_ptr< LiquidProductionConstraint >( &liquidConstraint ); + // Set properties from VFP table + FunctionManager & functionManager = FunctionManager::getInstance(); + const PipeFlowTableFunction & m_flowTable = functionManager.getGroup< PipeFlowTableFunction const >( m_minWHPConstraint->getFlowTableName()); + string_array ratePhases = m_flowTable.getRatePhases(); + m_maxLiquidConstraintForWHP->setPhaseNames( ratePhases ); + m_maxLiquidConstraintForWHP->validateLiquidType( getMultiFluidSeparator()); + // WHP estimator solve will set status + m_maxLiquidConstraintForWHP->setConstraintActive( false ); +} + +void WellControls::expandObjectCatalogs() +{ + //createChild( keys::wellControls, keys::wellControls ); +} + void WellControls::switchToBHPControl( real64 const & val ) { m_currentControl = Control::BHP; @@ -306,6 +419,7 @@ void WellControls::postInputInitialization() InputError ); // 4) check that at least one rate constraint has been defined +#if 0 GEOS_THROW_IF( ((m_targetPhaseRate <= 0.0 && m_targetPhaseRateTableName.empty()) && (m_targetMassRate <= 0.0 && m_targetMassRateTableName.empty()) && (m_targetTotalRate <= 0.0 && m_targetTotalRateTableName.empty())), @@ -320,7 +434,7 @@ void WellControls::postInputInitialization() "either " << viewKeyStruct::targetMassRateString() << " or " << viewKeyStruct::targetMassRateTableNameString(), InputError ); - +#endif // 5) check whether redundant information has been provided GEOS_THROW_IF( ((m_targetPhaseRate > 0.0 && !m_targetPhaseRateTableName.empty())), "WellControls " << getDataContext() << ": You have provided redundant information for well phase rate." << @@ -346,6 +460,13 @@ void WellControls::postInputInitialization() "WellControls " << getDataContext() << ": Option only valid if useSurfaceConditions set to 1", InputError ); + GEOS_THROW_IF( ((m_useSurfaceConditions==1 && m_surfacePres< 0.0)), + "WellControls " << getDataContext() << " " << viewKeyStruct::surfacePressureString()<< " not set ", + InputError ); + GEOS_THROW_IF( ((m_useSurfaceConditions==1 && m_surfaceTemp<0.0)), + "WellControls " << getDataContext() << " " << viewKeyStruct::surfaceTemperatureString()<< " not set ", + InputError ); + // 6.1) If the well is under BHP control then the BHP must be specified. // Otherwise the BHP will be set to a default value. if( m_currentControl == Control::BHP ) @@ -497,9 +618,30 @@ bool WellControls::isWellOpen() const return getWellStatus() == WellControls::Status::OPEN; } +void WellControls::setWellState( bool open ) +{ + m_wellOpen = open; +} + +bool WellControls::getWellState() const +{ + return m_wellOpen; +} + +void WellControls::setConstraintSwitch( bool constraintSwitch ) +{ + m_constraintSwitch = constraintSwitch; +} + +bool WellControls::getConstraintSwitch() const +{ + return m_constraintSwitch; +} + void WellControls::setNextDtFromTables( real64 const & currentTime, real64 & nextDt ) { + // replace with iter over constraints - tjb WellControls::setNextDtFromTable( m_targetBHPTable, currentTime, nextDt ); WellControls::setNextDtFromTable( m_targetMassRateTable, currentTime, nextDt ); WellControls::setNextDtFromTable( m_targetPhaseRateTable, currentTime, nextDt ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp index 301c3c42f7c..67216530306 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp @@ -26,6 +26,13 @@ #include "functions/TableFunction.hpp" #include "constitutive/fluid/multifluid/MultiFluidBase.hpp" +#include "physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp" +#include "constitutive/fluid/multifluid/MultiFluidBase.hpp" + namespace geos { namespace dataRepository @@ -123,6 +130,18 @@ class WellControls : public dataRepository::Group ///@} + /** + * @brief Create a new geometric object (box, plane, etc) as a child of this group. + * @param childKey the catalog key of the new geometric object to create + * @param childName the name of the new geometric object in the repository + * @return the group child + */ + virtual Group * createChild( string const & childKey, string const & childName ) override; + /// Expand catalog for schema generation + + virtual void expandObjectCatalogs() override; + + /** * @name Getters / Setters */ @@ -284,6 +303,18 @@ class WellControls : public dataRepository::Group */ bool isWellOpen() const; + void setWellState( bool open ); + bool getWellState() const; + + + void setConstraintSwitch( bool constraintSwitch ); + bool getConstraintSwitch() const; + + void setCurrentConstraint( WellConstraintBase * currentConstraint ) { m_currentConstraint = currentConstraint;} + WellConstraintBase * getCurrentConstraint() { return m_currentConstraint; } + WellConstraintBase const * getCurrentConstraint() const { return m_currentConstraint; } + + /** * @brief Getter for the flag to enable crossflow * @return the flag deciding whether crossflow is allowed or not @@ -303,6 +334,13 @@ class WellControls : public dataRepository::Group */ void setNextDtFromTables( real64 const & currentTime, real64 & nextDt ); + /** + * @brief getter for esitmator switch + * @return True if estimate well solution + */ + integer estimateSolution() const { return m_estimateSolution; } + + /** * @brief setter for multi fluid separator * @param[in] fluidSeparatorPtr single or multiphase separator @@ -404,13 +442,52 @@ class WellControls : public dataRepository::Group static constexpr char const * enableCrossflowString() { return "enableCrossflow"; } /// string key for the initial pressure coefficient static constexpr char const * initialPressureCoefficientString() { return "initialPressureCoefficient"; } - + /// string key for the esitmate well solution flag + static constexpr char const * estimateWellSolutionString() { return "estimateWellSolution"; } + + /// string key for the minimum BHP presssure for a producer + static constexpr char const * minimumBHPConstraintString() { return "MinimumBHPConstraint"; } + /// string key for the maximum BHP presssure for a injection + static constexpr char const * maximumBHPConstraintString() { return "MaximumBHPConstraint"; } + /// string key for the maximum phase rate for a producer + static constexpr char const * phaseProductionConstraintString() { return "PhaseProductionConstraint"; } + /// string key for the maximum phase rate for a injection + static constexpr char const * phaseInjectionConstraintString() { return "PhaseInjectionConstraint"; } + /// string key for the maximum volume rate for a producer + static constexpr char const * totalVolProductionConstraintString() { return "TotalVolProductionConstraint"; } + /// string key for the maximum volume rate for a injector + static constexpr char const * totalVolInjectionConstraintString() { return "TotalVolInjectionConstraint"; } + /// string key for the maximum mass rate for a producer + static constexpr char const * massProductionConstraintString() { return "massProductionConstraint"; } + /// string key for the maximum mass rate for a injector + static constexpr char const * massInjectionConstraintString() { return "massInjectionConstraint"; } + /// string key for the liquid rate for a producer + static constexpr char const * liquidProductionConstraintString() { return "liquidProductionConstraint"; } } /// ViewKey struct for the WellControls class viewKeysWellControls; static void setNextDtFromTable( TableFunction const * table, real64 const currentTime, real64 & nextDt ); + /** + * @brief Create a constraint + * @tparam ConstraintType the type of constraint to create + * @param[in] constraintName name to assign to the constraint + */ + template< typename ConstraintType > void createConstraint ( string const & constraintName ); + + + /** + * @brief Getters for constraints + */ + std::shared_ptr< MinimumBHPConstraint > getMinBHPConstraint() { return m_minBHPConstraint; }; + std::shared_ptr< MaximumBHPConstraint > getMaxBHPConstraint() { return m_maxBHPConstraint; }; + + std::shared_ptr< LiquidProductionConstraint > getMaxLiquidConstraintForWHP() { return m_maxLiquidConstraintForWHP; }; + std::shared_ptr< MinimumBHPConstraint > getMinimumBHPConstraintForWHP() { return m_minBHPConstraintForWHP; }; + // Lists of rate constraints + std::vector< std::shared_ptr< WellConstraintBase > > getProdRateConstraints() { return m_productionRateConstraintList; }; + std::vector< std::shared_ptr< WellConstraintBase > > getInjRateConstraints() { return m_injectionRateConstraintList; } protected: virtual void postInputInitialization() override; @@ -512,6 +589,28 @@ class WellControls : public dataRepository::Group /// Status table TableFunction const * m_statusTable; + bool m_wellOpen; + + /// flag to use the estimator + integer m_estimateSolution; + + /// List of constraints + //constraint_array m_ConstraintList; + // Bool to trigger old/new constraint switch logic + bool m_constraintSwitch; + + // Current constraint + WellConstraintBase * m_currentConstraint; + // Minimum and maximum BHP and WHP constraints + std::shared_ptr< MinimumBHPConstraint > m_minBHPConstraint; + std::shared_ptr< MaximumBHPConstraint > m_maxBHPConstraint; + + + // Lists of rate constraints + std::vector< std::shared_ptr< WellConstraintBase > > m_productionRateConstraintList; + std::vector< std::shared_ptr< WellConstraintBase > > m_injectionRateConstraintList; + + /// Well status WellControls::Status m_wellStatus; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.cpp new file mode 100644 index 00000000000..bb8cf202dd9 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.cpp @@ -0,0 +1,85 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellConstraint.cpp + */ + +#include "LogLevelsInfo.hpp" +#include "WellLiquidRateConstraints.hpp" +#include "WellConstants.hpp" +#include "dataRepository/InputFlags.hpp" +#include "functions/FunctionManager.hpp" + + +namespace geos +{ + +using namespace dataRepository; + +// *** Liquid Constraint for Production Well *************************************************************** +LiquidConstraint::LiquidConstraint( string const & name, Group * const parent ) + : WellConstraintBase( name, parent ) +{ + setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); + registerWrapper( viewKeyStruct::liquidRateString(), &m_constraintValue ). + setDefaultValue( 0.0 ). + setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). + setDescription( "Phase rate, (if useSurfaceConditions: [surface m^3/s]; else [reservoir m^3/s]) " ); + + registerWrapper( viewKeyStruct::phaseNamesString(), &m_phaseNames ). + setRTTypeName( rtTypes::CustomTypes::groupNameRef ). + setDefaultValue( "" ). + setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). + setDescription( "Name of the target phase" ); +} + +LiquidConstraint::~LiquidConstraint() +{} + +void LiquidConstraint::postInputInitialization() +{ + // Validate value and table options + WellConstraintBase::postInputInitialization(); +} + + +// *** Liquid Constraint for Production Well *************************************************************** +LiquidProductionConstraint::LiquidProductionConstraint( string const & name, Group * const parent ) + : LiquidConstraint( name, parent ) +{ + m_rateSign=-1.0; +} + +LiquidProductionConstraint::~LiquidProductionConstraint() +{} + +void LiquidProductionConstraint::postInputInitialization() +{ + // Validate value and table options + LiquidConstraint::postInputInitialization(); + +} + +bool LiquidProductionConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const +{ + return currentConstraint.liquidRate() < getConstraintValue( currentTime ); +} + + + +} //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp new file mode 100644 index 00000000000..d8fce1733b4 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp @@ -0,0 +1,242 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellLiquidRateConstraints.hpp + */ + + +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLLIQUIDRATECONSTRAINTS_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLLIQUIDRATECONSTRAINTS_HPP + +#include "common/format/EnumStrings.hpp" +#include "dataRepository/Group.hpp" +#include "functions/TableFunction.hpp" +#include "WellConstraintsBase.hpp" + +namespace geos +{ + + +/** + * @class LiquidConstraint + * @brief This class describes a Liquid rate constraint used to control a production well. + */ + +class LiquidConstraint : public WellConstraintBase +{ +public: + + + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for WellControls Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit LiquidConstraint( string const & name, dataRepository::Group * const parent ); + + + /** + * @brief Default destructor. + */ + ~LiquidConstraint() override; + + /** + * @brief Deleted default constructor. + */ + LiquidConstraint() = delete; + + /** + * @brief Deleted copy constructor. + */ + LiquidConstraint( LiquidConstraint const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + LiquidConstraint( LiquidConstraint && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + LiquidConstraint & operator=( LiquidConstraint const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + LiquidConstraint & operator=( LiquidConstraint && ) = delete; + + ///@} + + /** + * @name Getters / Setters + */ + ///@{ + /** + * @brief Get the target phase name + * @return the target phase name + */ + const string_array & getPhaseNames() const { return m_phaseNames; } + + /** + * @brief Set phases associated with liquid constraint + * @param array of phase names + */ + void setPhaseNames( const string_array & phaseNames ) { m_phaseNames=phaseNames; } + + /** + * @brief Get the phase indices + * @return array of phase indices + */ + const array1d< integer > & getPhaseIndices() const { return m_phaseIndices; } + + ///@} + /** + * @brief Struct to serve as a container for variable strings and keys. + * @struct viewKeyStruct + */ + struct viewKeyStruct + { + /// String key for the liquid rate + static constexpr char const * liquidRateString() { return "liquidRate"; } + /// String key for the phases names + static constexpr char const * phaseNamesString() { return "phaseNames"; } + }; + + // Temp interface - tjb + virtual ConstraintTypeId getControl() const override { return ConstraintTypeId::LIQUIDRATE; }; + + +protected: + + virtual void postInputInitialization() override; + +protected: + + /// Name of the targeted phase + string_array m_phaseNames; + ///Indices of the phases defining the fluid + array1d< integer > m_phaseIndices; + +}; + +/** + * @class LiquidProductionConstraint + * @brief This class describes a Liquid rate constraint used to control a production well. + */ + +class LiquidProductionConstraint : public LiquidConstraint +{ +public: + + + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for WellControls Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit LiquidProductionConstraint( string const & name, dataRepository::Group * const parent ); + + + /** + * @brief Default destructor. + */ + ~LiquidProductionConstraint() override; + + /** + * @brief Deleted default constructor. + */ + LiquidProductionConstraint() = delete; + + /** + * @brief Deleted copy constructor. + */ + LiquidProductionConstraint( LiquidProductionConstraint const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + LiquidProductionConstraint( LiquidProductionConstraint && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + LiquidProductionConstraint & operator=( LiquidProductionConstraint const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + LiquidProductionConstraint & operator=( LiquidProductionConstraint && ) = delete; + + ///@} + + /** + * @name Getters / Setters + */ + ///@{ + + /** + * @brief Get name of constraint + * @return constraint key + */ + virtual std::string getConstraintKey( ) const override { return "LiquidProductionConstraint"; }; + + + virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const override; + ///@} + + /** + * @brief Validate Liquid type is consistent with fluidmodel + */ + template< typename T > void validateLiquidType( T const & fluidModel ); +protected: + + virtual void postInputInitialization() override; + +}; + +template< typename T > +void LiquidProductionConstraint::validateLiquidType( T const & fluidModel ) +{ + m_phaseIndices.resize( m_phaseNames.size()); + for( size_t ip =0; ip( LiquidConstraint::viewKeyStruct::liquidRateString()) << + ": Invalid Liquid type for simulation fluid model " << m_phaseNames[ip], + InputError ); + m_phaseIndices[ip]=phaseIndex; + } +} + + +} //namespace geos + +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINT_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.cpp new file mode 100644 index 00000000000..63cc38d9918 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.cpp @@ -0,0 +1,109 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellMassRateConstraints.cpp + */ + +#include "LogLevelsInfo.hpp" +#include "WellMassRateConstraints.hpp" +#include "WellConstants.hpp" +#include "dataRepository/InputFlags.hpp" +#include "functions/FunctionManager.hpp" + + +namespace geos +{ + +using namespace dataRepository; + + +MassConstraint::MassConstraint( string const & name, Group * const parent ) + : WellConstraintBase( name, parent ) +{ + setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); +} + +MassConstraint::~MassConstraint() +{} + +void MassConstraint::postInputInitialization() +{ + // Validate value and table options + WellConstraintBase::postInputInitialization(); + +} + +MassProductionConstraint::MassProductionConstraint( string const & name, Group * const parent ) + : MassConstraint( name, parent ) +{ + m_rateSign = -1.0; + setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); + registerWrapper( constraintViewStruct::constraintValueKey::constraintValueString(), &m_constraintValue ). + setDefaultValue( 0.0 ). + setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). + setDescription( "Maximum mass injection rate (if useSurfaceConditions: [surface m^3/s]; else [reservoir m^3/s])" ); + +} + + +MassProductionConstraint::~MassProductionConstraint() +{} + +void MassProductionConstraint::postInputInitialization() +{ + // Validate value and table options + MassConstraint::postInputInitialization(); + +} + +bool MassProductionConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const +{ + return currentConstraint.massRate() < getConstraintValue( currentTime ); +} + + +MassInjectionConstraint::MassInjectionConstraint( string const & name, Group * const parent ) + : MassConstraint( name, parent ) +{ + setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); + + registerWrapper( constraintViewStruct::constraintValueKey::constraintValueString(), &m_constraintValue ). + setDefaultValue( 0.0 ). + setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). + setDescription( "Maximum mass injection rate (if useSurfaceConditions: [surface m^3/s]; else [reservoir m^3/s])" ); +} + +MassInjectionConstraint::~MassInjectionConstraint() +{} + +void MassInjectionConstraint::postInputInitialization() +{ + // Validate value and table options + MassConstraint::postInputInitialization(); + +// Validate the injection stream and temperature + validateInjectionStream( m_injectionStream, m_injectionTemperature, getConstraintKey(), *this ); +} + +bool MassInjectionConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime )const +{ + return currentConstraint.massRate() > getConstraintValue( currentTime ); +} + + +} //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp new file mode 100644 index 00000000000..41039458e32 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp @@ -0,0 +1,273 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellMassRateConstraints.hpp + */ + + +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLMASSRATECONSTRAINTS_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLMASSRATECONSTRAINTS_HPP + +#include "common/format/EnumStrings.hpp" +#include "dataRepository/Group.hpp" +#include "functions/TableFunction.hpp" +#include "WellConstraintsBase.hpp" +namespace geos +{ + +/** + * @class MassConstraint + * @brief This class describes a mass rate constraint used to control a well. + */ + +class MassConstraint : public WellConstraintBase +{ +public: + + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for WellControls Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit MassConstraint( string const & name, dataRepository::Group * const parent ); + + + /** + * @brief Default destructor. + */ + ~MassConstraint() override; + + /** + * @brief Deleted default constructor. + */ + MassConstraint() = delete; + + /** + * @brief Deleted copy constructor. + */ + MassConstraint( MassConstraint const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + MassConstraint( MassConstraint && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + MassConstraint & operator=( MassConstraint const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + MassConstraint & operator=( MassConstraint && ) = delete; + + ///@} + + /** + * @name Getters / Setters + */ + + // Temp interface - tjb + virtual ConstraintTypeId getControl() const override { return ConstraintTypeId::MASSRATE; }; + ///@} + + +protected: + + virtual void postInputInitialization() override; + + + +}; + + +/** + * @class MassProductionConstraint + * @brief This class describes a mass rate constraint used to control a production well. + */ + +class MassProductionConstraint : public MassConstraint +{ +public: + + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for WellControls Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit MassProductionConstraint( string const & name, dataRepository::Group * const parent ); + + + /** + * @brief Default destructor. + */ + ~MassProductionConstraint() override; + + /** + * @brief Deleted default constructor. + */ + MassProductionConstraint() = delete; + + /** + * @brief Deleted copy constructor. + */ + MassProductionConstraint( MassProductionConstraint const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + MassProductionConstraint( MassProductionConstraint && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + MassProductionConstraint & operator=( MassProductionConstraint const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + MassProductionConstraint & operator=( MassProductionConstraint && ) = delete; + + ///@} + + /** + * @name Getters / Setters + */ + + /** + * @brief Get name of constraint + * @return constraint key + */ + virtual std::string getConstraintKey( ) const override { return "MassProductionConstraint"; }; + ///@} + + virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const override; + +protected: + + virtual void postInputInitialization() override; + + + +}; + +/** + * @class MassInjectionConstraint + * @brief This class describes a Mass rate constraint used to control a injection well. + */ + +class MassInjectionConstraint : public MassConstraint +{ +public: + + + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for MassInjectionConstraint Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit MassInjectionConstraint( string const & name, dataRepository::Group * const parent ); + + + /** + * @brief Default destructor. + */ + ~MassInjectionConstraint() override; + + /** + * @brief Deleted default constructor. + */ + MassInjectionConstraint() = delete; + + /** + * @brief Deleted copy constructor. + */ + MassInjectionConstraint( MassInjectionConstraint const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + MassInjectionConstraint( MassInjectionConstraint && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + MassInjectionConstraint & operator=( MassInjectionConstraint const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + MassInjectionConstraint & operator=( MassInjectionConstraint && ) = delete; + + ///@} + + /** + * @name Getters / Setters + */ + ///@{ + /** + * @brief Get name of constraint + * @return constraint key + */ + virtual std::string getConstraintKey( ) const override { return "MassInjectionConstraint"; }; + ///@} + + // Injection stream definition keys + constraintViewStruct::injectionStreamKey viewKeysInjectionStream; + + virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const override; + +protected: + + virtual void postInputInitialization() override; + +private: + + /// Vector with global component fractions at the injector + array1d< real64 > m_injectionStream; + + /// Temperature at the injector + real64 m_injectionTemperature; + +}; + + + +} //namespace geos + +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINT_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.cpp new file mode 100644 index 00000000000..d52c494258b --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.cpp @@ -0,0 +1,126 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellConstraint.cpp + */ + +#include "LogLevelsInfo.hpp" +#include "WellPhaseRateConstraints.hpp" +#include "WellConstants.hpp" +#include "dataRepository/InputFlags.hpp" +#include "functions/FunctionManager.hpp" + + +namespace geos +{ + +using namespace dataRepository; + +// *** Phase Constraint for Production Well *************************************************************** +PhaseConstraint::PhaseConstraint( string const & name, Group * const parent ) + : WellConstraintBase( name, parent ), + m_phaseIndex( -1 ) +{ + setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); + + registerWrapper( viewKeyStruct::phaseRateString(), &m_constraintValue ). + setDefaultValue( 0.0 ). + setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). + setDescription( "Phase rate, (if useSurfaceConditions: [surface m^3/s]; else [reservoir m^3/s]) " ); + + registerWrapper( viewKeyStruct::phaseNameString(), &m_phaseName ). + setRTTypeName( rtTypes::CustomTypes::groupNameRef ). + setDefaultValue( "" ). + setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). + setDescription( "Name of the target phase" ); + +} + +PhaseConstraint::~PhaseConstraint() +{} + +void PhaseConstraint::postInputInitialization() +{ + // Validate value and table options + WellConstraintBase::postInputInitialization(); +} + + +// *** Phase Constraint for Production Well *************************************************************** +PhaseProductionConstraint::PhaseProductionConstraint( string const & name, Group * const parent ) + : PhaseConstraint( name, parent ) +{ + m_rateSign=-1.0; +} + +PhaseProductionConstraint::~PhaseProductionConstraint() +{} + +void PhaseProductionConstraint::postInputInitialization() +{ + // Validate value and table options + PhaseConstraint::postInputInitialization(); + +} + +bool PhaseProductionConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const +{ + return currentConstraint.phaseVolumeRates()[m_phaseIndex] < getConstraintValue( currentTime ); +} + + + +// *** Phase Constraint for Injection Well *************************************************************** +PhaseInjectionConstraint::PhaseInjectionConstraint( string const & name, Group * const parent ) + : PhaseConstraint( name, parent ) +{ + registerWrapper( constraintViewStruct::injectionStreamKey::injectionStreamString(), &m_injectionStream ). + setDefaultValue( -1 ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Global component densities of the injection stream [moles/m^3 or kg/m^3]" ); + + registerWrapper( constraintViewStruct::injectionStreamKey::injectionTemperatureString(), &m_injectionTemperature ). + setDefaultValue( -1 ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Temperature of the injection stream [K]" ); +} + + +PhaseInjectionConstraint::~PhaseInjectionConstraint() +{} + +void PhaseInjectionConstraint::postInputInitialization() +{ + + // Validate value and table options + PhaseConstraint::postInputInitialization(); + +// Validate the injection stream and temperature + validateInjectionStream( m_injectionStream, m_injectionTemperature, getConstraintKey(), *this ); + +} + +bool PhaseInjectionConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const +{ + return currentConstraint.phaseVolumeRates()[m_phaseIndex] > getConstraintValue( currentTime ); +} + + + +} //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp new file mode 100644 index 00000000000..55c881ad0a5 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp @@ -0,0 +1,354 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellPhaseRateConstraints.hpp + */ + + +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLPHASERATECONSTRAINTS_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLPHASERATECONSTRAINTS_HPP + +#include "common/format/EnumStrings.hpp" +#include "dataRepository/Group.hpp" +#include "functions/TableFunction.hpp" +#include "WellConstraintsBase.hpp" + +namespace geos +{ + + +template< typename T > +localIndex getPhaseIndex( T const & fluidModel, std::string const & inputPhase ) +{ + localIndex phaseIndex=-1; + // Find target phase index for phase rate constraint + for( integer ip = 0; ip < fluidModel.numFluidPhases(); ++ip ) + { + if( fluidModel.phaseNames()[ip] == inputPhase ) + { + phaseIndex = ip; + } + } + return phaseIndex; +}; + +/** + * @class PhaseConstraint + * @brief This class describes a phase rate constraint used to control a production well. + */ + +class PhaseConstraint : public WellConstraintBase +{ +public: + + + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for WellControls Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit PhaseConstraint( string const & name, dataRepository::Group * const parent ); + + + /** + * @brief Default destructor. + */ + ~PhaseConstraint() override; + + /** + * @brief Deleted default constructor. + */ + PhaseConstraint() = delete; + + /** + * @brief Deleted copy constructor. + */ + PhaseConstraint( PhaseConstraint const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + PhaseConstraint( PhaseConstraint && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + PhaseConstraint & operator=( PhaseConstraint const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + PhaseConstraint & operator=( PhaseConstraint && ) = delete; + + ///@} + + /** + * @name Getters / Setters + */ + ///@{ + + // Temp interface - tjb + virtual ConstraintTypeId getControl() const override { return ConstraintTypeId::PHASEVOLRATE; }; + + /** + * @brief Get the target phase name + * @return the target phase name + */ + const string & getPhaseName() const { return m_phaseName; } + + ///@} + + struct viewKeyStruct + { + /// String key for the well target phase rate + static constexpr char const * phaseRateString() { return "phaseRate"; } + /// String key for the well target phase name + static constexpr char const * phaseNameString() { return "phaseName"; } + }; + +protected: + + virtual void postInputInitialization() override; + +protected: + /// Name of the targeted phase + string m_phaseName; + + /// Index of the target phase, used to impose the phase rate constraint + localIndex m_phaseIndex; + +}; + + +/** + * @class PhaseProductionConstraint + * @brief This class describes a phase rate constraint used to control a production well. + */ + +class PhaseProductionConstraint : public PhaseConstraint +{ +public: + + + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for WellControls Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit PhaseProductionConstraint( string const & name, dataRepository::Group * const parent ); + + + /** + * @brief Default destructor. + */ + ~PhaseProductionConstraint() override; + + /** + * @brief Deleted default constructor. + */ + PhaseProductionConstraint() = delete; + + /** + * @brief Deleted copy constructor. + */ + PhaseProductionConstraint( PhaseProductionConstraint const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + PhaseProductionConstraint( PhaseProductionConstraint && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + PhaseProductionConstraint & operator=( PhaseProductionConstraint const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + PhaseProductionConstraint & operator=( PhaseProductionConstraint && ) = delete; + + ///@} + + /** + * @name Getters / Setters + */ + ///@{ + + /** + * @brief Get name of constraint + * @return constraint key + */ + virtual std::string getConstraintKey( ) const override { return "PhaseProductionConstraint"; }; + + + virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const override; + ///@} + + /** + * @brief Validate phase type is consistent with fluidmodel + */ + template< typename T > void validatePhaseType( T const & fluidModel ); +protected: + + virtual void postInputInitialization() override; + +}; + +template< typename T > +void PhaseProductionConstraint::validatePhaseType( T const & fluidModel ) +{ + // Find target phase index for phase rate constraint + m_phaseIndex = getPhaseIndex( fluidModel, getReference< string >( PhaseConstraint::viewKeyStruct::phaseNameString())); + + GEOS_THROW_IF( m_phaseIndex == -1, + "PhaseProductionConstraint " << getReference< string >( PhaseConstraint::viewKeyStruct::phaseNameString()) << + ": Invalid phase type for simulation fluid model", + InputError ); +} + +/** + * @class PhaseInjectionConstraint + * @brief This class describes a phase rate constraint used to control a injection well. + */ + +class PhaseInjectionConstraint : public PhaseConstraint +{ +public: + + + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for WellControls Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit PhaseInjectionConstraint( string const & name, dataRepository::Group * const parent ); + + + /** + * @brief Default destructor. + */ + ~PhaseInjectionConstraint() override; + + /** + * @brief Deleted default constructor. + */ + PhaseInjectionConstraint() = delete; + + /** + * @brief Deleted copy constructor. + */ + PhaseInjectionConstraint( PhaseInjectionConstraint const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + PhaseInjectionConstraint( PhaseInjectionConstraint && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + PhaseInjectionConstraint & operator=( PhaseInjectionConstraint const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + PhaseInjectionConstraint & operator=( PhaseInjectionConstraint && ) = delete; + + ///@} + + /** + * @name Getters / Setters + */ + ///@{ + + /** + * @brief Get name of constraint + * @return constraint key + */ + virtual std::string getConstraintKey( ) const override { return "PhaseInjectionConstraint"; }; + ///@} + + /** + * @brief Struct to serve as a container for variable strings and keys. + * @struct viewKeyStruct + */ + struct injectionStreamKey + { + /// String key for the well injection stream + static constexpr char const * injectionStreamString() { return "injectionStream"; } + /// String key for the well injection temperature + static constexpr char const * injectionTemperatureString() { return "injectionTemperature"; } + }; + + /** + * @brief Validate phase type is consistent with fluidmodel + */ + template< typename T > void validatePhaseType( T const & fluidModel ); + ///@} + + virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const override; +protected: + + virtual void postInputInitialization() override; + +private: + + /// Vector with global component fractions at the injector + array1d< real64 > m_injectionStream; + + /// Temperature at the injector + real64 m_injectionTemperature; + +}; + + +template< typename T > +void PhaseInjectionConstraint::validatePhaseType( T const & fluidModel ) +{ + // Find target phase index for phase rate constraint + m_phaseIndex = getPhaseIndex( fluidModel, getReference< string >( PhaseConstraint::viewKeyStruct::phaseNameString())); + + GEOS_THROW_IF( m_phaseIndex == -1, + "PhaseInjectionConstraint " << getReference< string >( PhaseConstraint::viewKeyStruct::phaseNameString()) << + ": Invalid phase type for simulation fluid model", + InputError ); +} + +} //namespace geos + +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINT_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.cpp new file mode 100644 index 00000000000..86f974925d9 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.cpp @@ -0,0 +1,107 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellTotalVolRateConstraints.cpp + */ + +#include "LogLevelsInfo.hpp" +#include "WellTotalVolRateConstraints.hpp" +#include "WellConstants.hpp" +#include "dataRepository/InputFlags.hpp" +#include "functions/FunctionManager.hpp" + + +namespace geos +{ + +using namespace dataRepository; + +TotalVolConstraint::TotalVolConstraint( string const & name, Group * const parent ) + : WellConstraintBase( name, parent ) +{ + setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); + registerWrapper( viewKeyStruct::volumeRateString(), &m_constraintValue ). + setDefaultValue( 0.0 ). + setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). + setDescription( "Volumetric rate (if useSurfaceConditions: [surface m^3/s]; else [reservoir m^3/s])" ); + +} + + +TotalVolConstraint::~TotalVolConstraint() +{} + +void TotalVolConstraint::postInputInitialization() +{ + WellConstraintBase::postInputInitialization(); + +} + + +TotalVolProductionConstraint::TotalVolProductionConstraint( string const & name, Group * const parent ) + : TotalVolConstraint( name, parent ) +{ + setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); + m_rateSign=-1.0; + +} + + +TotalVolProductionConstraint::~TotalVolProductionConstraint() +{} + +void TotalVolProductionConstraint::postInputInitialization() +{ + TotalVolConstraint::postInputInitialization(); + +} + +bool TotalVolProductionConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime )const +{ + return currentConstraint.totalVolumeRate() < getConstraintValue( currentTime ); +} + + +TotalVolInjectionConstraint::TotalVolInjectionConstraint( string const & name, Group * const parent ) + : TotalVolConstraint( name, parent ) +{ + setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); + + + // Field registration + registerInjectionStream( m_injectionStream, m_injectionTemperature, *this ); +} + + +TotalVolInjectionConstraint::~TotalVolInjectionConstraint() +{} + +void TotalVolInjectionConstraint::postInputInitialization() +{ + + TotalVolConstraint::postInputInitialization(); +// Validate the injection stream and temperature + validateInjectionStream( m_injectionStream, m_injectionTemperature, getConstraintKey(), *this ); + +} + +bool TotalVolInjectionConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime )const +{ + return currentConstraint.totalVolumeRate() > getConstraintValue( currentTime ); +} + +} //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp new file mode 100644 index 00000000000..90d8cf36211 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp @@ -0,0 +1,286 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellVolumeRateConstraints.hpp + */ + + +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLTOTALVOLRATECONSTRAINTS_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLTOTALVOLRATECONSTRAINTS_HPP + +#include "common/format/EnumStrings.hpp" +#include "dataRepository/Group.hpp" +#include "functions/TableFunction.hpp" +#include "WellConstraintsBase.hpp" +namespace geos +{ +namespace dataRepository +{ +namespace keys +{ +static constexpr auto totalVolProductionConstraint = "TotalVolProductionConstraint"; +static constexpr auto totalVolInjectionConstraint = "TotalVolInjectionConstraint"; +} +} + + +/** + * @class TotalVolConstraint + * @brief This class describes a volume rate constraint used to control a well. + */ + +class TotalVolConstraint : public WellConstraintBase +{ +public: + + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for WellControls Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit TotalVolConstraint( string const & name, dataRepository::Group * const parent ); + + + /** + * @brief Default destructor. + */ + ~TotalVolConstraint() override; + + /** + * @brief Deleted default constructor. + */ + TotalVolConstraint() = delete; + + /** + * @brief Deleted copy constructor. + */ + TotalVolConstraint( TotalVolConstraint const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + TotalVolConstraint( TotalVolConstraint && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + TotalVolConstraint & operator=( TotalVolConstraint const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + TotalVolConstraint & operator=( TotalVolConstraint && ) = delete; + + ///@} + /** + * @brief Struct to serve as a container for variable strings and keys. + * @struct viewKeyStruct + */ + struct viewKeyStruct + { + /// String key for the volume rate + static constexpr char const * volumeRateString() { return "volumeRate"; } + }; + /** + * @name Getters / Setters + */ + ///@{ + /** + * @brief Get name of constraint + * @return constraint key + */ + virtual std::string getConstraintKey( ) const override { return "TotalVolInjectionConstraint"; }; + ///@} + + // Temp interface - tjb + virtual ConstraintTypeId getControl() const override { return ConstraintTypeId::TOTALVOLRATE; }; + +protected: + + virtual void postInputInitialization() override; + +}; + + +/** + * @class TotalVolProductionConstraint + * @brief This class describes a volume rate constraint used to control a production well. + */ + +class TotalVolProductionConstraint : public TotalVolConstraint +{ +public: + + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for WellControls Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit TotalVolProductionConstraint( string const & name, dataRepository::Group * const parent ); + + + /** + * @brief Default destructor. + */ + ~TotalVolProductionConstraint() override; + + /** + * @brief Deleted default constructor. + */ + TotalVolProductionConstraint() = delete; + + /** + * @brief Deleted copy constructor. + */ + TotalVolProductionConstraint( TotalVolProductionConstraint const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + TotalVolProductionConstraint( TotalVolProductionConstraint && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + TotalVolProductionConstraint & operator=( TotalVolProductionConstraint const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + TotalVolProductionConstraint & operator=( TotalVolProductionConstraint && ) = delete; + + ///@} + + /** + * @name Getters / Setters + */ + ///@{ + /** + * @brief Get name of constraint + * @return constraint key + */ + virtual std::string getConstraintKey( ) const override { return "TotalVolProductionConstraint"; }; + ///@} + + virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const override; +protected: + + virtual void postInputInitialization() override; + +}; + +/** + * @class TotalVolInjectionConstraint + * @brief This class describes a volume rate constraint used to control a injection well. + */ + +class TotalVolInjectionConstraint : public TotalVolConstraint +{ +public: + + + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for TotalVolInjectionConstraint Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit TotalVolInjectionConstraint( string const & name, dataRepository::Group * const parent ); + + + /** + * @brief Default destructor. + */ + ~TotalVolInjectionConstraint() override; + + /** + * @brief Deleted default constructor. + */ + TotalVolInjectionConstraint() = delete; + + /** + * @brief Deleted copy constructor. + */ + TotalVolInjectionConstraint( TotalVolInjectionConstraint const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + TotalVolInjectionConstraint( TotalVolInjectionConstraint && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + TotalVolInjectionConstraint & operator=( TotalVolInjectionConstraint const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + TotalVolInjectionConstraint & operator=( TotalVolInjectionConstraint && ) = delete; + + ///@} + + /** + * @name Getters / Setters + */ + ///@{ + + + ///@} + + // Injection stream definition keys + constraintViewStruct::injectionStreamKey viewKeysInjectionStream; + + virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const override; +protected: + + virtual void postInputInitialization() override; + +private: + + /// Vector with global component fractions at the injector + array1d< real64 > m_injectionStream; + + /// Temperature at the injector + real64 m_injectionTemperature; + +}; + + + +} //namespace geos + +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINT_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp index 039ae5c1813..aff9a909137 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp @@ -37,7 +37,7 @@ GEOS_HOST_DEVICE inline void ControlEquationHelper:: - switchControl( bool const isProducer, + selectLimitingConstraint( bool const isProducer, WellControls::Control const & inputControl, WellControls::Control const & currentControl, integer const phasePhaseIndex, @@ -140,6 +140,7 @@ ControlEquationHelper:: real64 const & targetPhaseRate, real64 const & targetTotalRate, real64 const & targetMassRate, + real64 const & targetValue, real64 const & currentBHP, arrayView1d< real64 const > const & dCurrentBHP, arrayView1d< real64 const > const & currentPhaseVolRate, @@ -152,7 +153,7 @@ ControlEquationHelper:: CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - + GEOS_UNUSED_VAR( targetValue ); // tjb keeping this around if needed to compare with old constraint eqn jacgen using COFFSET_WJ = compositionalMultiphaseWellKernels::ColOffset_WellJac< NC, IS_THERMAL >; using Deriv = multifluid::DerivativeOffset; @@ -321,11 +322,18 @@ PressureRelationKernel:: bool const isProducer = wellControls.isProducer(); WellControls::Control const currentControl = wellControls.getControl(); WellControls::Control const inputControl = wellControls.getInputControl(); + bool const constraintSwitch = wellControls.getConstraintSwitch(); + real64 const targetBHP = wellControls.getTargetBHP( time ); real64 const targetTotalRate = wellControls.getTargetTotalRate( time ); real64 const targetPhaseRate = wellControls.getTargetPhaseRate( time ); real64 const targetMassRate = wellControls.getTargetMassRate( time ); + // temp tjb. only needed if new code path + real64 targetValue =0.0; + if( wellControls.getCurrentConstraint() != nullptr ) + targetValue = wellControls.getCurrentConstraint()->getConstraintValue( time ); + // dynamic well control data real64 const & currentBHP = wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() ); @@ -364,7 +372,10 @@ PressureRelationKernel:: { WellControls::Control newControl = currentControl; - ControlEquationHelper::switchControl( isProducer, + if( false && constraintSwitch ) + { + + ControlEquationHelper::selectLimitingConstraint( isProducer, inputControl, currentControl, targetPhaseIndex, @@ -377,17 +388,26 @@ PressureRelationKernel:: currentTotalVolRate, currentMassRate, newControl ); + } + else + { + newControl = currentControl; + } + if( currentControl != newControl ) { switchControl.max( 1 ); } + if( constraintSwitch ) + { ControlEquationHelper::compute< NC, IS_THERMAL >( rankOffset, newControl, - targetPhaseIndex, - targetBHP, - targetPhaseRate, - targetTotalRate, - targetMassRate, + targetPhaseIndex, // tjb - remove ? + targetBHP, // tjb - remove + targetPhaseRate, // tjb - remove + targetTotalRate, // tjb - remove + targetMassRate, // tjb - remove + targetValue, // tjb currentBHP, dCurrentBHP, currentPhaseVolRate, @@ -398,6 +418,7 @@ PressureRelationKernel:: wellElemDofNumber[iwelemControl], localMatrix, localRhs ); + } // TODO: for consistency, we should assemble here, not in compute... } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp index a8123abbb12..6e28ff049e9 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp @@ -134,7 +134,7 @@ struct ControlEquationHelper inline static void - switchControl( bool const isProducer, + selectLimitingConstraint( bool const isProducer, WellControls::Control const & inputControl, WellControls::Control const & currentControl, integer const phasePhaseIndex, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/WellConstraintKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/WellConstraintKernels.hpp new file mode 100644 index 00000000000..250fca30455 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/WellConstraintKernels.hpp @@ -0,0 +1,568 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file WellConstraintKernels.hpp + */ + +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINTKERNELS_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINTKERNELS_HPP + +#include "codingUtilities/Utilities.hpp" +#include "constitutive/fluid/multifluid/MultiFluidBase.hpp" +#include "constitutive/fluid/multifluid/MultiFluidFields.hpp" + + +#include "physicsSolvers/fluidFlow/wells/WellControls.hpp" +#include "physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp" +namespace geos +{ + +namespace wellConstraintKernels +{ + +/******************************** ControlEquationHelper ********************************/ +template< integer NC, integer IS_THERMAL, typename T > +struct ConstraintHelper {}; + +template< integer NC, integer IS_THERMAL > +struct ConstraintHelper< NC, IS_THERMAL, BHPConstraint > +{ + static void assembleConstraintEquation( real64 const & time_n, + WellControls & wellControls, + BHPConstraint & constraint, + WellElementSubRegion const & subRegion, + string const & wellDofKey, + localIndex const & rankOffset, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) + { + // subRegion data + localIndex const iwelemRef = subRegion.getTopWellElementIndex(); + arrayView1d< globalIndex const > const & wellElemDofNumber = subRegion.getReference< array1d< globalIndex > >( wellDofKey ); + arrayView1d< real64 const > const & pres = subRegion.getField< fields::well::pressure >(); + arrayView1d< real64 const > const & totalMassDens = subRegion.getField< fields::well::totalMassDensity >(); + arrayView2d< real64 const > const & dTotalMassDens = subRegion.getField< fields::well::dTotalMassDensity >(); + arrayView1d< real64 const > const wellElemGravCoef = subRegion.getField< fields::well::gravityCoefficient >(); + + // setup row/column indices for constraint equation + using COFFSET_WJ = compositionalMultiphaseWellKernels::ColOffset_WellJac< NC, IS_THERMAL >; + using WJ_ROFFSET = compositionalMultiphaseWellKernels::RowOffset_WellJac< NC, IS_THERMAL >; + using Deriv = constitutive::multifluid::DerivativeOffset; + + localIndex const eqnRowIndex = wellElemDofNumber[iwelemRef] + WJ_ROFFSET::CONTROL - rankOffset; + globalIndex dofColIndices[COFFSET_WJ::nDer]{}; + for( integer ic = 0; ic < COFFSET_WJ::nDer; ++ic ) + { + dofColIndices[ ic ] = wellElemDofNumber[iwelemRef] + ic; + } + + // constraint data + real64 const & targetBHP = constraint.getConstraintValue( time_n ); + real64 const & refGravCoef = constraint.getReferenceGravityCoef(); + + // current constraint value + real64 const & currentBHP = + wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() ); + + // residual + real64 controlEqn = currentBHP - targetBHP; + + // setup Jacobian terms + real64 dControlEqn[NC+2+IS_THERMAL]{}; + + // bring everything back to host, capture the scalars by reference + forAll< serialPolicy >( 1, [pres, + totalMassDens, + dTotalMassDens, + wellElemGravCoef, + &dControlEqn, + &iwelemRef, + &refGravCoef] ( localIndex const ) + { + real64 const diffGravCoef = refGravCoef - wellElemGravCoef[iwelemRef]; + dControlEqn[COFFSET_WJ::dP] = 1 + dTotalMassDens[iwelemRef][Deriv::dP] * diffGravCoef; + for( integer ic = 0; ic < NC; ++ic ) + { + dControlEqn[COFFSET_WJ::dC+ic] = dTotalMassDens[iwelemRef][Deriv::dC+ic] * diffGravCoef; + } + if constexpr ( IS_THERMAL ) + { + dControlEqn[COFFSET_WJ::dT] = dTotalMassDens[iwelemRef][Deriv::dT] * diffGravCoef; + } + } ); + + // add solver matrices + localRhs[eqnRowIndex] += controlEqn; + localMatrix.addToRowBinarySearchUnsorted< serialAtomic >( eqnRowIndex, + dofColIndices, + dControlEqn, + COFFSET_WJ::nDer ); + } +}; + +template< integer NC, integer IS_THERMAL > +struct ConstraintHelper< NC, IS_THERMAL, PhaseConstraint > +{ + static void assembleConstraintEquation( real64 const & time_n, + WellControls & wellControls, + PhaseConstraint & constraint, + WellElementSubRegion const & subRegion, + string const & wellDofKey, + localIndex const & rankOffset, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) + { + // subRegion data + + localIndex const iwelemRef = subRegion.getTopWellElementIndex(); + arrayView1d< globalIndex const > const & wellElemDofNumber = subRegion.getReference< array1d< globalIndex > >( wellDofKey ); + arrayView1d< real64 const > const & connRate = subRegion.getField< fields::well::mixtureConnectionRate >(); + arrayView2d< real64 const, compflow::USD_COMP > const & compFrac = subRegion.getField< fields::well::globalCompFraction >(); + arrayView3d< real64 const, compflow::USD_COMP_DC > const & dCompFrac_dCompDens = subRegion.getField< fields::well::dGlobalCompFraction_dGlobalCompDensity >(); + + // setup row/column indices for constraint equation + using COFFSET_WJ = compositionalMultiphaseWellKernels::ColOffset_WellJac< NC, IS_THERMAL >; + using WJ_ROFFSET = compositionalMultiphaseWellKernels::RowOffset_WellJac< NC, IS_THERMAL >; + using Deriv = constitutive::multifluid::DerivativeOffset; + + localIndex const eqnRowIndex = wellElemDofNumber[iwelemRef] + WJ_ROFFSET::CONTROL - rankOffset; + globalIndex dofColIndices[COFFSET_WJ::nDer]{}; + for( integer ic = 0; ic < COFFSET_WJ::nDer; ++ic ) + { + dofColIndices[ ic ] = wellElemDofNumber[iwelemRef] + ic; + } + + // fluid data + constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); + + arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const & phaseFrac = fluidSeparator.phaseFraction(); + arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > const & dPhaseFrac = fluidSeparator.dPhaseFraction(); + arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const & phaseDens = fluidSeparator.phaseDensity(); + arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > const & dPhaseDens = fluidSeparator.dPhaseDensity(); + + // constraint data + integer ip = getPhaseIndex( fluidSeparator, constraint.getPhaseName()); + real64 const & targetPhaseRate = constraint.getConstraintValue( time_n ); + + // current constraint value + arrayView1d< real64 > const & currentPhaseVolRate = + wellControls.getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ); + integer const useSurfaceConditions = wellControls.useSurfaceConditions(); + + // residual + real64 controlEqn = currentPhaseVolRate[ip] - targetPhaseRate; + + // setup Jacobian terms + real64 dControlEqn[NC+2+IS_THERMAL]{}; + + // bring everything back to host, capture the scalars by reference + forAll< serialPolicy >( 1, [&ip, + connRate, + phaseDens, + dPhaseDens, + phaseFrac, + dPhaseFrac, + compFrac, + dCompFrac_dCompDens, + &dControlEqn, + &useSurfaceConditions, + &iwelemRef] ( localIndex const ) + { + // skip the rest of this function if phase ip is absent + bool const phaseExists = (phaseFrac[iwelemRef][0][ip] > 0); + if( phaseExists ) + { + stackArray1d< real64, NC > work( NC ); + real64 const currentTotalRate = connRate[iwelemRef]; + + real64 const phaseDensInv = 1.0 / phaseDens[iwelemRef][0][ip]; + real64 const phaseFracTimesPhaseDensInv = phaseFrac[iwelemRef][0][ip] * phaseDensInv; + real64 const dPhaseFracTimesPhaseDensInv_dPres = dPhaseFrac[iwelemRef][0][ip][Deriv::dP] * phaseDensInv + - dPhaseDens[iwelemRef][0][ip][Deriv::dP] * phaseFracTimesPhaseDensInv * phaseDensInv; + + // divide the total mass/molar rate by the (phase density * phase fraction) to get the phase volumetric rate + dControlEqn[COFFSET_WJ::dP] = ( useSurfaceConditions == 0 ) * currentTotalRate * dPhaseFracTimesPhaseDensInv_dPres; + dControlEqn[COFFSET_WJ::dQ] = phaseFracTimesPhaseDensInv; + if constexpr (IS_THERMAL ) + { + real64 const dPhaseFracTimesPhaseDensInv_dTemp = dPhaseFrac[iwelemRef][0][ip][Deriv::dT] * phaseDensInv + - dPhaseDens[iwelemRef][0][ip][Deriv::dT] * phaseFracTimesPhaseDensInv * phaseDensInv; + dControlEqn[COFFSET_WJ::dT] = ( useSurfaceConditions == 0 ) * currentTotalRate * dPhaseFracTimesPhaseDensInv_dTemp; + } + + for( integer ic = 0; ic < NC; ++ic ) + { + dControlEqn[COFFSET_WJ::dC+ic] = -phaseFracTimesPhaseDensInv * dPhaseDens[iwelemRef][0][ip][Deriv::dC+ic] * phaseDensInv; + dControlEqn[COFFSET_WJ::dC+ic] += dPhaseFrac[iwelemRef][0][ip][Deriv::dC+ic] * phaseDensInv; + dControlEqn[COFFSET_WJ::dC+ic] *= currentTotalRate; + } + applyChainRuleInPlace( NC, dCompFrac_dCompDens[iwelemRef], &dControlEqn[COFFSET_WJ::dC], work.data() ); + + } + } ); + + // add solver matrices + localRhs[eqnRowIndex] += controlEqn; + localMatrix.addToRowBinarySearchUnsorted< serialAtomic >( eqnRowIndex, + dofColIndices, + dControlEqn, + COFFSET_WJ::nDer ); + } +}; + +template< integer NC, integer IS_THERMAL > +struct ConstraintHelper< NC, IS_THERMAL, LiquidConstraint > +{ + static void assembleConstraintEquation( real64 const & time_n, + WellControls & wellControls, + LiquidConstraint & constraint, + WellElementSubRegion const & subRegion, + string const & wellDofKey, + localIndex const & rankOffset, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) + { + // subRegion data + + localIndex const iwelemRef = subRegion.getTopWellElementIndex(); + arrayView1d< globalIndex const > const & wellElemDofNumber = subRegion.getReference< array1d< globalIndex > >( wellDofKey ); + arrayView1d< real64 const > const & connRate = subRegion.getField< fields::well::mixtureConnectionRate >(); + arrayView2d< real64 const, compflow::USD_COMP > const & compFrac = subRegion.getField< fields::well::globalCompFraction >(); + arrayView3d< real64 const, compflow::USD_COMP_DC > const & dCompFrac_dCompDens = subRegion.getField< fields::well::dGlobalCompFraction_dGlobalCompDensity >(); + + // setup row/column indices for constraint equation + using COFFSET_WJ = compositionalMultiphaseWellKernels::ColOffset_WellJac< NC, IS_THERMAL >; + using WJ_ROFFSET = compositionalMultiphaseWellKernels::RowOffset_WellJac< NC, IS_THERMAL >; + using Deriv = constitutive::multifluid::DerivativeOffset; + + localIndex const eqnRowIndex = wellElemDofNumber[iwelemRef] + WJ_ROFFSET::CONTROL - rankOffset; + globalIndex dofColIndices[COFFSET_WJ::nDer]{}; + for( integer ic = 0; ic < COFFSET_WJ::nDer; ++ic ) + { + dofColIndices[ ic ] = wellElemDofNumber[iwelemRef] + ic; + } + + // fluid data + constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); + + arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const & phaseFrac = fluidSeparator.phaseFraction(); + arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > const & dPhaseFrac = fluidSeparator.dPhaseFraction(); + arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const & phaseDens = fluidSeparator.phaseDensity(); + arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > const & dPhaseDens = fluidSeparator.dPhaseDensity(); + + // constraint data + real64 const & targetPhaseRate = constraint.getConstraintValue( time_n ); + const array1d< int > & phaseIndices = constraint.getPhaseIndices(); + + + // current constraint value + arrayView1d< real64 > const & currentPhaseVolRate = + wellControls.getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ); + integer const useSurfaceConditions = wellControls.useSurfaceConditions(); + + // residual + real64 controlEqn = -targetPhaseRate; + for( integer ip= 0; ip < phaseIndices.size(); ++ip ) + { + controlEqn += currentPhaseVolRate[phaseIndices[ip]]; + } + + // setup Jacobian terms + real64 dControlEqn[NC+2+IS_THERMAL]{}; + + // bring everything back to host, capture the scalars by reference + forAll< serialPolicy >( 1, [phaseIndices, + connRate, + phaseDens, + dPhaseDens, + phaseFrac, + dPhaseFrac, + compFrac, + dCompFrac_dCompDens, + &dControlEqn, + &useSurfaceConditions, + &iwelemRef] ( localIndex const ) + { + + stackArray1d< real64, NC > work( NC ); + for( integer i= 0; i < phaseIndices.size(); ++i ) + { + integer ip = phaseIndices[i]; + bool const phaseExists = (phaseFrac[iwelemRef][0][ip] > 0); + // skip the rest of this function if phase ip is absent + if( phaseExists ) + { + + real64 const currentTotalRate = connRate[iwelemRef]; + + real64 const phaseDensInv = 1.0 / phaseDens[iwelemRef][0][ip]; + real64 const phaseFracTimesPhaseDensInv = phaseFrac[iwelemRef][0][ip] * phaseDensInv; + real64 const dPhaseFracTimesPhaseDensInv_dPres = dPhaseFrac[iwelemRef][0][ip][Deriv::dP] * phaseDensInv + - dPhaseDens[iwelemRef][0][ip][Deriv::dP] * phaseFracTimesPhaseDensInv * phaseDensInv; + + // divide the total mass/molar rate by the (phase density * phase fraction) to get the phase volumetric rate + dControlEqn[COFFSET_WJ::dP] += ( useSurfaceConditions == 0 ) * currentTotalRate * dPhaseFracTimesPhaseDensInv_dPres; + dControlEqn[COFFSET_WJ::dQ] += phaseFracTimesPhaseDensInv; + if constexpr (IS_THERMAL ) + { + real64 const dPhaseFracTimesPhaseDensInv_dTemp = dPhaseFrac[iwelemRef][0][ip][Deriv::dT] * phaseDensInv + - dPhaseDens[iwelemRef][0][ip][Deriv::dT] * phaseFracTimesPhaseDensInv * phaseDensInv; + dControlEqn[COFFSET_WJ::dT] += ( useSurfaceConditions == 0 ) * currentTotalRate * dPhaseFracTimesPhaseDensInv_dTemp; + } + + for( integer ic = 0; ic < NC; ++ic ) + { + real64 temp = -phaseFracTimesPhaseDensInv * dPhaseDens[iwelemRef][0][ip][Deriv::dC+ic] * phaseDensInv; + temp += dPhaseFrac[iwelemRef][0][ip][Deriv::dC+ic] * phaseDensInv; + temp *= currentTotalRate; + dControlEqn[COFFSET_WJ::dC+ic] += temp; + } + } + } + applyChainRuleInPlace( NC, dCompFrac_dCompDens[iwelemRef], &dControlEqn[COFFSET_WJ::dC], work.data() ); + } ); + + // add solver matrices + localRhs[eqnRowIndex] += controlEqn; + localMatrix.addToRowBinarySearchUnsorted< serialAtomic >( eqnRowIndex, + dofColIndices, + dControlEqn, + COFFSET_WJ::nDer ); + } +}; + +template< integer NC, integer IS_THERMAL > +struct ConstraintHelper< NC, IS_THERMAL, TotalVolConstraint > +{ + static void assembleConstraintEquation( real64 const & time_n, + WellControls & wellControls, + TotalVolConstraint & constraint, + WellElementSubRegion const & subRegion, + string const & wellDofKey, + localIndex const & rankOffset, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) + { + // subRegion data + + localIndex const iwelemRef = subRegion.getTopWellElementIndex(); + arrayView1d< globalIndex const > const & wellElemDofNumber = subRegion.getReference< array1d< globalIndex > >( wellDofKey ); + arrayView1d< real64 const > const & connRate = subRegion.getField< fields::well::mixtureConnectionRate >(); + arrayView2d< real64 const, compflow::USD_COMP > const & compFrac = subRegion.getField< fields::well::globalCompFraction >(); + arrayView3d< real64 const, compflow::USD_COMP_DC > const & dCompFrac_dCompDens = subRegion.getField< fields::well::dGlobalCompFraction_dGlobalCompDensity >(); + + // setup row/column indices for constraint equation + using COFFSET_WJ = compositionalMultiphaseWellKernels::ColOffset_WellJac< NC, IS_THERMAL >; + using WJ_ROFFSET = compositionalMultiphaseWellKernels::RowOffset_WellJac< NC, IS_THERMAL >; + using Deriv = constitutive::multifluid::DerivativeOffset; + + localIndex const eqnRowIndex = wellElemDofNumber[iwelemRef] + WJ_ROFFSET::CONTROL - rankOffset; + globalIndex dofColIndices[COFFSET_WJ::nDer]{}; + for( integer ic = 0; ic < COFFSET_WJ::nDer; ++ic ) + { + dofColIndices[ ic ] = wellElemDofNumber[iwelemRef] + ic; + } + + // fluid data + constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); + + arrayView2d< real64 const, constitutive::multifluid::USD_FLUID > const & totalDens = fluidSeparator.totalDensity(); + arrayView3d< real64 const, constitutive::multifluid::USD_FLUID_DC > const & dTotalDens = fluidSeparator.dTotalDensity(); + + // constraint data + real64 const & targetTotalVolRate = constraint.getConstraintValue( time_n ); + + // current constraint value + real64 const & currentTotalVolRate = + wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() ); + integer const useSurfaceConditions = wellControls.useSurfaceConditions(); + + // residual + real64 controlEqn = currentTotalVolRate - targetTotalVolRate; + + // setup Jacobian terms + real64 dControlEqn[NC+2+IS_THERMAL]{}; + + // bring everything back to host, capture the scalars by reference + forAll< serialPolicy >( 1, [connRate, + totalDens, + dTotalDens, + compFrac, + dCompFrac_dCompDens, + &dControlEqn, + &useSurfaceConditions, + &iwelemRef] ( localIndex const ) + { + stackArray1d< real64, NC > work( NC ); + + real64 const currentTotalRate = connRate[iwelemRef]; + + // compute the inverse of the total density and derivatives + + real64 const totalDensInv = 1.0 / totalDens[iwelemRef][0]; + + stackArray1d< real64, NC > dTotalDensInv_dCompDens( NC ); + for( integer ic = 0; ic < NC; ++ic ) + { + dTotalDensInv_dCompDens[ic] = -dTotalDens[iwelemRef][0][Deriv::dC+ic] * totalDensInv * totalDensInv; + } + applyChainRuleInPlace( NC, dCompFrac_dCompDens[iwelemRef], dTotalDensInv_dCompDens, work.data() ); + + // Step 2.2: divide the total mass/molar rate by the total density to get the total volumetric rate + + // Compute derivatives dP dT + real64 const dTotalDensInv_dPres = -dTotalDens[iwelemRef][0][Deriv::dP] * totalDensInv * totalDensInv; + dControlEqn[COFFSET_WJ::dP] = ( useSurfaceConditions == 0 ) * currentTotalRate * dTotalDensInv_dPres; + if constexpr ( IS_THERMAL ) + { + dControlEqn[COFFSET_WJ::dT] = ( useSurfaceConditions == 0 ) * currentTotalRate * -dTotalDens[iwelemRef][0][Deriv::dT] * totalDensInv * totalDensInv; + } + + dControlEqn[COFFSET_WJ::dQ] = totalDensInv; + for( integer ic = 0; ic < NC; ++ic ) + { + dControlEqn[COFFSET_WJ::dC+ic] = currentTotalRate * dTotalDensInv_dCompDens[ic]; + } + + } ); + + // add solver matrices + localRhs[eqnRowIndex] += controlEqn; + localMatrix.addToRowBinarySearchUnsorted< serialAtomic >( eqnRowIndex, + dofColIndices, + dControlEqn, + COFFSET_WJ::nDer ); + } +}; + +template< integer NC, integer IS_THERMAL > +struct ConstraintHelper< NC, IS_THERMAL, MassConstraint > +{ + static void assembleConstraintEquation( real64 const & time_n, + WellControls & wellControls, + MassConstraint & constraint, + WellElementSubRegion const & subRegion, + string const & wellDofKey, + localIndex const & rankOffset, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) + { + // subRegion data + + localIndex const iwelemRef = subRegion.getTopWellElementIndex(); + arrayView1d< globalIndex const > const & wellElemDofNumber = subRegion.getReference< array1d< globalIndex > >( wellDofKey ); + arrayView1d< real64 const > const & connRate = subRegion.getField< fields::well::mixtureConnectionRate >(); + arrayView2d< real64 const, compflow::USD_COMP > const & compFrac = subRegion.getField< fields::well::globalCompFraction >(); + arrayView3d< real64 const, compflow::USD_COMP_DC > const & dCompFrac_dCompDens = subRegion.getField< fields::well::dGlobalCompFraction_dGlobalCompDensity >(); + + // setup row/column indices for constraint equation + using COFFSET_WJ = compositionalMultiphaseWellKernels::ColOffset_WellJac< NC, IS_THERMAL >; + using WJ_ROFFSET = compositionalMultiphaseWellKernels::RowOffset_WellJac< NC, IS_THERMAL >; + using Deriv = constitutive::multifluid::DerivativeOffset; + + localIndex const eqnRowIndex = wellElemDofNumber[iwelemRef] + WJ_ROFFSET::CONTROL - rankOffset; + globalIndex dofColIndices[COFFSET_WJ::nDer]{}; + for( integer ic = 0; ic < COFFSET_WJ::nDer; ++ic ) + { + dofColIndices[ ic ] = wellElemDofNumber[iwelemRef] + ic; + } + + // fluid data + constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); + arrayView2d< real64 const, constitutive::multifluid::USD_FLUID > const & totalDens = fluidSeparator.totalDensity(); + arrayView3d< real64 const, constitutive::multifluid::USD_FLUID_DC > const & dTotalDens = fluidSeparator.dTotalDensity(); + + // constraint data + real64 const & targetMassRate = constraint.getConstraintValue( time_n ); + + // current constraint value + real64 const & massDensity = + wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::massDensityString() ); + + // fix to use stored massrate + real64 const & currentTotalVolRate = + wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() ); + integer const useSurfaceConditions = wellControls.useSurfaceConditions(); + + // residual + real64 controlEqn = massDensity*currentTotalVolRate - targetMassRate; + + // setup Jacobian terms + real64 dControlEqn[NC+2+IS_THERMAL]{}; + + // bring everything back to host, capture the scalars by reference + forAll< serialPolicy >( 1, [connRate, + massDensity, + totalDens, + dTotalDens, + compFrac, + dCompFrac_dCompDens, + &dControlEqn, + &useSurfaceConditions, + &iwelemRef] ( localIndex const ) + { + stackArray1d< real64, NC > work( NC ); + + real64 const currentTotalRate = connRate[iwelemRef]; + + // compute the inverse of the total density and derivatives + + real64 const totalDensInv = 1.0 / totalDens[iwelemRef][0]; + + stackArray1d< real64, NC > dTotalDensInv_dCompDens( NC ); + for( integer ic = 0; ic < NC; ++ic ) + { + dTotalDensInv_dCompDens[ic] = -dTotalDens[iwelemRef][0][Deriv::dC+ic] * totalDensInv * totalDensInv; + } + applyChainRuleInPlace( NC, dCompFrac_dCompDens[iwelemRef], dTotalDensInv_dCompDens, work.data() ); + + // Step 2.2: divide the total mass/molar rate by the total density to get the total volumetric rate + + // Compute derivatives dP dT + real64 const dTotalDensInv_dPres = -dTotalDens[iwelemRef][0][Deriv::dP] * totalDensInv * totalDensInv; + dControlEqn[COFFSET_WJ::dP] = ( useSurfaceConditions == 0 )*massDensity * currentTotalRate * dTotalDensInv_dPres; + if constexpr ( IS_THERMAL ) + { + dControlEqn[COFFSET_WJ::dT] = ( useSurfaceConditions == 0 ) * massDensity* currentTotalRate * -dTotalDens[iwelemRef][0][Deriv::dT] * totalDensInv * totalDensInv; + } + + dControlEqn[COFFSET_WJ::dQ] = massDensity*totalDensInv; + for( integer ic = 0; ic < NC; ++ic ) + { + dControlEqn[COFFSET_WJ::dC+ic] = massDensity* currentTotalRate * dTotalDensInv_dCompDens[ic]; + } + + } ); + + // add solver matrices + localRhs[eqnRowIndex] += controlEqn; + localMatrix.addToRowBinarySearchUnsorted< serialAtomic >( eqnRowIndex, + dofColIndices, + dControlEqn, + COFFSET_WJ::nDer ); + } +}; + + +} // end namespace wellConstraintKernels + +} // end namespace geos + +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINTKERNELS_HPP diff --git a/src/coreComponents/schema/schema.xsd b/src/coreComponents/schema/schema.xsd index b4480011c41..c9b84e61719 100644 --- a/src/coreComponents/schema/schema.xsd +++ b/src/coreComponents/schema/schema.xsd @@ -3370,6 +3370,8 @@ When set to 2 also output convergence information to a csv--> + + @@ -5163,6 +5165,8 @@ When set to 2 also output convergence information to a csv--> + + From a9cd276707563d2ab7148461b68cf7704fc91ff2 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Mon, 29 Sep 2025 18:12:11 -0700 Subject: [PATCH 02/71] fix merge errors --- .../wells/CompositionalMultiphaseWell.cpp | 2301 +++++++++++++---- .../wells/CompositionalMultiphaseWell.hpp | 146 ++ .../fluidFlow/wells/SinglePhaseWell.cpp | 7 + .../fluidFlow/wells/SinglePhaseWell.hpp | 2 +- .../fluidFlow/wells/WellControls.cpp | 34 +- .../fluidFlow/wells/WellControls.hpp | 4 +- .../fluidFlow/wells/WellSolverBase.cpp | 282 +- .../fluidFlow/wells/WellSolverBase.hpp | 153 +- .../CompositionalMultiphaseWellKernels.cpp | 72 +- .../CompositionalMultiphaseWellKernels.hpp | 25 +- 10 files changed, 2417 insertions(+), 609 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 14537f0d999..50d9ead0bb7 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -50,6 +50,16 @@ #include "physicsSolvers/fluidFlow/kernels/compositional/FluidUpdateKernel.hpp" #include "physicsSolvers/fluidFlow/CompositionalMultiphaseStatistics.hpp" +#include "physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp" + +#include "physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/kernels/WellConstraintKernels.hpp" + + + #if defined( __INTEL_COMPILER ) #pragma GCC optimize "O0" #endif @@ -469,6 +479,15 @@ void CompositionalMultiphaseWell::validateWellConstraints( real64 const & time_n string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString()); MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); + // tjb + wellControls.forSubGroups< PhaseProductionConstraint, PhaseInjectionConstraint >( [&]( auto & constraint ) + { + constraint.validatePhaseType( fluid ); + } ); + + + // now that we know we are single-phase, we can check a few things in the constraints + WellControls::Control const currentControl = wellControls.getControl(); real64 const & targetTotalRate = wellControls.getTargetTotalRate( time_n ); real64 const & targetPhaseRate = wellControls.getTargetPhaseRate( time_n ); @@ -919,6 +938,122 @@ void CompositionalMultiphaseWell::updateVolRatesForConstraint( WellElementSubReg } ); } +void CompositionalMultiphaseWell::calculateReferenceElementRates( WellElementSubRegion & subRegion ) +{ + GEOS_MARK_FUNCTION; + + // the rank that owns the reference well element is responsible for the calculations below. + if( !subRegion.isLocallyOwned() ) + { + return; + } + + integer const numPhase = m_numPhases; + localIndex const iwelemRef = subRegion.getTopWellElementIndex(); + + WellControls & wellControls = getWellControls( subRegion ); + + // subRegion data + arrayView1d< real64 const > const & connRate = subRegion.getField< fields::well::mixtureConnectionRate >(); + + // fluid data + constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); + arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const & phaseFrac = fluidSeparator.phaseFraction(); + arrayView2d< real64 const, constitutive::multifluid::USD_FLUID > const & totalDens = fluidSeparator.totalDensity(); + arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const & phaseDens = fluidSeparator.phaseDensity(); + + // control data + string const wellControlsName = wellControls.getName(); + bool const logSurfaceCondition = isLogLevelActive< logInfo::BoundaryConditions >( wellControls.getLogLevel()); + string const massUnit = m_useMass ? "kg" : "mol"; + + integer const useSurfaceConditions = wellControls.useSurfaceConditions(); + + arrayView1d< real64 > const & currentPhaseVolRate = + wellControls.getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ); + + real64 & currentTotalVolRate = + wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() ); + + real64 & currentMassRate = + wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() ); + + real64 & massDensity = + wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::massDensityString() ); + + constitutive::constitutiveUpdatePassThru( fluidSeparator, [&] ( auto & castedFluidSeparator ) + { + // typename TYPEOFREF( castedFluid ) ::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); + typename TYPEOFREF( castedFluidSeparator ) ::KernelWrapper fluidSeparatorWrapper = castedFluidSeparator.createKernelWrapper(); + + // bring everything back to host, capture the scalars by reference + forAll< serialPolicy >( 1, [fluidSeparatorWrapper, + &numPhase, + connRate, + totalDens, + phaseDens, + phaseFrac, + logSurfaceCondition, + &useSurfaceConditions, + ¤tTotalVolRate, + currentPhaseVolRate, + ¤tMassRate, + &iwelemRef, + &wellControlsName, + &massUnit, + &massDensity] ( localIndex const ) + { + GEOS_UNUSED_VAR( massUnit ); + + + // 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 + massDensity = totalDens[iwelemRef][0]; + real64 const totalDensInv = 1.0 / totalDens[iwelemRef][0]; + + + // Step 2.2: divide the total mass/molar rate by the total density to get the total volumetric rate + currentTotalVolRate = currentTotalRate * totalDensInv; + + + if( logSurfaceCondition && useSurfaceConditions ) + { + GEOS_LOG_RANK( GEOS_FMT( "{}: total fluid density at surface conditions = {} {}/sm3, total rate = {} {}/s, total surface volumetric rate = {} sm3/s", + wellControlsName, totalDens[iwelemRef][0], massUnit, connRate[iwelemRef], massUnit, currentTotalVolRate ) ); + } + + // Step 3: update the phase volume rate + for( integer ip = 0; ip < numPhase; ++ip ) + { + + // Step 3.1: compute the inverse of the (phase density * phase fraction) + + // skip the rest of this function if phase ip is absent + bool const phaseExists = (phaseFrac[iwelemRef][0][ip] > 0); + if( !phaseExists ) + { + continue; + } + + real64 const phaseDensInv = 1.0 / phaseDens[iwelemRef][0][ip]; + real64 const phaseFracTimesPhaseDensInv = phaseFrac[iwelemRef][0][ip] * phaseDensInv; + + // Step 3.2: divide the total mass/molar rate by the (phase density * phase fraction) to get the phase volumetric rate + currentPhaseVolRate[ip] = currentTotalRate * phaseFracTimesPhaseDensInv; + + if( logSurfaceCondition && useSurfaceConditions ) + { + GEOS_LOG_RANK( GEOS_FMT( "{}: density of phase {} at surface conditions = {} {}/sm3, phase surface volumetric rate = {} sm3/s", + wellControlsName, ip, phaseDens[iwelemRef][0][ip], massUnit, currentPhaseVolRate[ip] ) ); + } + } + } ); + } ); +} void CompositionalMultiphaseWell::updateFluidModel( WellElementSubRegion & subRegion ) @@ -947,6 +1082,81 @@ void CompositionalMultiphaseWell::updateFluidModel( WellElementSubRegion & subRe } +void CompositionalMultiphaseWell::updateSeparator( WellElementSubRegion & subRegion ) +{ + GEOS_MARK_FUNCTION; + + // the rank that owns the reference well element is responsible for the calculations below. + if( !subRegion.isLocallyOwned() ) + { + return; + } + + localIndex const iwelemRef = subRegion.getTopWellElementIndex(); + + WellControls & wellControls = getWellControls( subRegion ); + + // subRegion data + arrayView1d< real64 const > const & pres = subRegion.getField< fields::well::pressure >(); + arrayView1d< real64 const > const & temp = subRegion.getField< fields::well::temperature >(); + arrayView2d< real64 const, compflow::USD_COMP > const & compFrac = subRegion.getField< fields::well::globalCompFraction >(); + + + // fluid data + constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); + + // control data + + string const wellControlsName = wellControls.getName(); + bool const logSurfaceCondition = isLogLevelActive< logInfo::BoundaryConditions >( wellControls.getLogLevel()); + string const massUnit = m_useMass ? "kg" : "mol"; + + integer const useSurfaceConditions = wellControls.useSurfaceConditions(); + real64 const & surfacePres = wellControls.getSurfacePressure(); + real64 const & surfaceTemp = wellControls.getSurfaceTemperature(); + + constitutive::constitutiveUpdatePassThru( fluidSeparator, [&] ( auto & castedFluidSeparator ) + { + // typename TYPEOFREF( castedFluid ) ::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); + typename TYPEOFREF( castedFluidSeparator ) ::KernelWrapper fluidSeparatorWrapper = castedFluidSeparator.createKernelWrapper(); + // bring everything back to host, capture the scalars by reference + forAll< serialPolicy >( 1, [fluidSeparatorWrapper, + wellControlsName, + useSurfaceConditions, + surfacePres, + surfaceTemp, + logSurfaceCondition, + iwelemRef, + pres, + temp, + compFrac] ( localIndex const ) + { + // - Surface conditions: using the surface pressure provided by the user + // - Reservoir conditions: using the pressure in the top element + if( useSurfaceConditions ) + { + // we need to compute the surface density + //fluidWrapper.update( iwelemRef, 0, surfacePres, surfaceTemp, compFrac[iwelemRef] ); + fluidSeparatorWrapper.update( iwelemRef, 0, surfacePres, surfaceTemp, compFrac[iwelemRef] ); + if( logSurfaceCondition ) + { + GEOS_LOG_RANK( GEOS_FMT( "{}: surface density computed with P_surface = {} Pa and T_surface = {} K", + wellControlsName, surfacePres, surfaceTemp ) ); + } +#ifdef GEOS_USE_HIP + GEOS_UNUSED_VAR( wellControlsName ); +#endif + } + else + { + real64 const refPres = pres[iwelemRef]; + fluidSeparatorWrapper.update( iwelemRef, 0, refPres, temp[iwelemRef], compFrac[iwelemRef] ); + } + } ); + } ); +} + + real64 CompositionalMultiphaseWell::updatePhaseVolumeFraction( WellElementSubRegion & subRegion ) const { GEOS_MARK_FUNCTION; @@ -995,10 +1205,20 @@ void CompositionalMultiphaseWell::updateTotalMassDensity( WellElementSubRegion & } -void CompositionalMultiphaseWell::updateState( DomainPartition & domain ) +real64 CompositionalMultiphaseWell::updateWellState( WellElementSubRegion & subRegion ) { GEOS_MARK_FUNCTION; + real64 maxPhaseVolFrac = updateSubRegionState( subRegion ); + + return maxPhaseVolFrac; + +} + +void CompositionalMultiphaseWell::updateState( DomainPartition & domain ) +{ + GEOS_MARK_FUNCTION; + //tjb real64 maxPhaseVolFrac = 0.0; forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, @@ -1008,9 +1228,14 @@ void CompositionalMultiphaseWell::updateState( DomainPartition & domain ) WellElementSubRegion & subRegion ) { WellControls & wellControls = getWellControls( subRegion ); - if( wellControls.getWellStatus() == WellControls::Status::OPEN ) + if( wellControls.getWellState()) { +#if 1 + real64 const maxRegionPhaseVolFrac = updateWellState( subRegion ); +#else real64 const maxRegionPhaseVolFrac = updateSubRegionState( subRegion ); + +#endif maxPhaseVolFrac = LvArray::math::max( maxRegionPhaseVolFrac, maxPhaseVolFrac ); } } ); @@ -1025,30 +1250,236 @@ void CompositionalMultiphaseWell::updateState( DomainPartition & domain ) real64 CompositionalMultiphaseWell::updateSubRegionState( WellElementSubRegion & subRegion ) { - // update properties - updateGlobalComponentFraction( subRegion ); + real64 maxPhaseVolChange=0.0; + WellControls & wellControls = getWellControls( subRegion ); + if( wellControls.getWellState()) + { + if( m_useNewCode ) + { + // update properties + updateGlobalComponentFraction( subRegion ); - // update volumetric rates for the well constraints - // note: this must be called before updateFluidModel - updateVolRatesForConstraint( subRegion ); + // update volumetric rates for the well constraints + // note: this must be called before updateFluidModel - // update densities, phase fractions, phase volume fractions + updateVolRatesForConstraint( subRegion ); // remove - updateFluidModel( subRegion ); // Calculate fluid properties; - real64 maxPhaseVolChange = updatePhaseVolumeFraction( subRegion ); - updateTotalMassDensity( subRegion ); - // update the current BHP pressure - updateBHPForConstraint( subRegion ); + // update densities, phase fractions, phase volume fractions + + updateFluidModel( subRegion ); // Calculate fluid properties + + updateSeparator( subRegion ); // Calculate fluid properties at control conditions + + maxPhaseVolChange = updatePhaseVolumeFraction( subRegion ); + updateTotalMassDensity( subRegion ); + + // Calculate the reference element rates + calculateReferenceElementRates( subRegion ); + + // update the current BHP + updateBHPForConstraint( subRegion ); + + } + else + { + // update properties + updateGlobalComponentFraction( subRegion ); + + // update volumetric rates for the well constraints + // note: this must be called before updateFluidModel + + updateVolRatesForConstraint( subRegion ); + + // update densities, phase fractions, phase volume fractions + + updateFluidModel( subRegion ); // Calculate fluid properties; + maxPhaseVolChange = updatePhaseVolumeFraction( subRegion ); + updateTotalMassDensity( subRegion ); + // update the current BHP pressure + updateBHPForConstraint( subRegion ); + } + + } return maxPhaseVolChange; } -void CompositionalMultiphaseWell::initializeWells( DomainPartition & domain, real64 const & time_n ) +void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) { GEOS_MARK_FUNCTION; - + GEOS_UNUSED_VAR( domain ); integer const numComp = m_numComponents; integer const numPhase = m_numPhases; + m_nextDt = -1; + // TODO: change the way we access the flowSolver here + CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); + + + compositionalMultiphaseWellKernels::PresTempCompFracInitializationKernel::CompFlowAccessors + resCompFlowAccessors( mesh.getElemManager(), flowSolver.getName() ); + compositionalMultiphaseWellKernels::PresTempCompFracInitializationKernel::MultiFluidAccessors + resMultiFluidAccessors( mesh.getElemManager(), flowSolver.getName() ); + + WellControls & wellControls = getWellControls( subRegion ); + PerforationData const & perforationData = *subRegion.getPerforationData(); + arrayView2d< real64 const > const compPerfRate = perforationData.getField< fields::well::compPerforationRate >(); + + bool const hasNonZeroRate = MpiWrapper::max< integer >( hasNonZero( compPerfRate )); + + if( time_n <= 0.0 || ( wellControls.isWellOpen( ) && !hasNonZeroRate ) ) + { + // GEOS_LOG_RANK( "tjb initialize wells "<< subRegion.getName()); + if( !wellControls.getWellState() && isThermal() ) // tjb add as schema option + { + m_nextDt=43200; + } + wellControls.setWellState( true ); + // get well primary variables on well elements + arrayView1d< real64 > const & wellElemPressure = subRegion.getField< well::pressure >(); + arrayView1d< real64 > const & wellElemTemp = subRegion.getField< well::temperature >(); + arrayView2d< real64, compflow::USD_COMP > const & wellElemCompDens = subRegion.getField< well::globalCompDensity >(); + arrayView1d< real64 > const & connRate = subRegion.getField< well::mixtureConnectionRate >(); + + // get the info stored on well elements + arrayView2d< real64, compflow::USD_COMP > const & wellElemCompFrac = subRegion.getField< well::globalCompFraction >(); + arrayView1d< real64 const > const & wellElemGravCoef = subRegion.getField< well::gravityCoefficient >(); + + // get the element region, subregion, index + arrayView1d< localIndex const > const resElementRegion = perforationData.getField< perforation::reservoirElementRegion >(); + arrayView1d< localIndex const > const resElementSubRegion = perforationData.getField< perforation::reservoirElementSubRegion >(); + arrayView1d< localIndex const > const resElementIndex = perforationData.getField< perforation::reservoirElementIndex >(); + + arrayView1d< real64 const > const & perfGravCoef = perforationData.getField< fields::well::gravityCoefficient >(); + arrayView1d< integer const > const & perfStatus = perforationData.getField< fields::perforation::perforationStatus >(); + + // 1) Loop over all perforations to compute an average mixture density and component fraction + // 2) Initialize the reference pressure + // 3) Estimate the pressures in the well elements using the average density + compositionalMultiphaseWellKernels:: + PresTempCompFracInitializationKernel:: + launch( perforationData.size(), + subRegion.size(), + numComp, + numPhase, + wellControls, + 0.0, // initialization done at t = 0 + resCompFlowAccessors.get( flow::pressure{} ), + resCompFlowAccessors.get( flow::temperature{} ), + resCompFlowAccessors.get( flow::globalCompDensity{} ), + resCompFlowAccessors.get( flow::phaseVolumeFraction{} ), + resMultiFluidAccessors.get( fields::multifluid::phaseMassDensity{} ), + resElementRegion, + resElementSubRegion, + resElementIndex, + perfGravCoef, + perfStatus, + wellElemGravCoef, + wellElemPressure, + wellElemTemp, + wellElemCompFrac ); + + // get well secondary variables on well elements + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const & wellElemPhaseDens = fluid.phaseDensity(); + arrayView2d< real64 const, constitutive::multifluid::USD_FLUID > const & wellElemTotalDens = fluid.totalDensity(); + + // 4) Back calculate component densities + constitutive::constitutiveUpdatePassThru( fluid, [&] ( auto & castedFluid ) + { + typename TYPEOFREF( castedFluid ) ::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); + + thermalCompositionalMultiphaseBaseKernels:: + FluidUpdateKernel:: + launch< serialPolicy >( subRegion.size(), + fluidWrapper, + wellElemPressure, + wellElemTemp, + wellElemCompFrac ); + } ); + + compositionalMultiphaseWellKernels:: + CompDensInitializationKernel::launch( subRegion.size(), + numComp, + wellElemCompFrac, + wellElemTotalDens, + wellElemCompDens ); + + // 5) Recompute the pressure-dependent properties + updateSubRegionState( subRegion ); + + // 6) Estimate the well rates + // TODO: initialize rates using perforation rates + compositionalMultiphaseWellKernels:: + RateInitializationKernel:: + launch( subRegion.size(), + m_targetPhaseIndex, + wellControls, + time_n, // initialization done at time_n + wellElemPhaseDens, + wellElemTotalDens, + connRate ); + + updateVolRatesForConstraint( subRegion ); + + // 7) Copy well / fluid dofs to "prop"_n variables + saveState( subRegion ); + } + else if( !hasNonZeroRate ) + { + wellControls.setWellState( false ); + GEOS_LOG_RANK_0( "tjb shut wells "<< subRegion.getName()); + } + else + { + wellControls.setWellState( true ); + } + // Initialize well with pressure constraint + if( wellControls.getWellState( ) ) + { + if( wellControls.getCurrentConstraint() == nullptr ) + { + if( wellControls.isProducer() ) + { + wellControls.forSubGroups< MinimumBHPConstraint >( [&]( auto & constraint ) + //wellControls.forSubGroups< PhaseProductionConstraint >( [&]( auto & constraint + // ) + { + constraint.setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); + constraint.setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( + CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); + constraint.setTotalVolumeRate ( wellControls.getReference< real64 >( + CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); + constraint.setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); + wellControls.setCurrentConstraint( &constraint ); + wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old + } ); + } + else + { + // tjb needed for backward compatibility + //wellControls.forSubGroups< MaximumBHPConstraint >( [&]( auto & constraint ) + wellControls.forSubGroups< TotalVolInjectionConstraint >( [&]( auto & constraint ) + { + constraint.setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); + constraint.setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( + CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); + constraint.setTotalVolumeRate ( wellControls.getReference< real64 >( + CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); + constraint.setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); + wellControls.setCurrentConstraint( &constraint ); + wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old + } ); + } + } + } +} + + +void CompositionalMultiphaseWell::initializeWells( DomainPartition & domain, real64 const & time_n ) +{ + GEOS_MARK_FUNCTION; + m_nextDt = -1; // TODO: change the way we access the flowSolver here CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); @@ -1068,103 +1499,68 @@ void CompositionalMultiphaseWell::initializeWells( DomainPartition & domain, rea [&]( localIndex const, WellElementSubRegion & subRegion ) { - WellControls & wellControls = getWellControls( subRegion ); - PerforationData const & perforationData = *subRegion.getPerforationData(); - arrayView2d< real64 const > const compPerfRate = perforationData.getField< fields::well::compPerforationRate >(); - bool const hasNonZeroRate = MpiWrapper::max< integer >( hasNonZero( compPerfRate )); + initializeWell( domain, mesh, subRegion, time_n ); + } ); - if( wellControls.isWellOpen() && !hasNonZeroRate ) - { - // get well primary variables on well elements - arrayView1d< real64 > const & wellElemPressure = subRegion.getField< well::pressure >(); - arrayView1d< real64 > const & wellElemTemp = subRegion.getField< well::temperature >(); - arrayView2d< real64, compflow::USD_COMP > const & wellElemCompDens = subRegion.getField< well::globalCompDensity >(); - arrayView1d< real64 > const & connRate = subRegion.getField< well::mixtureConnectionRate >(); - - // get the info stored on well elements - arrayView2d< real64, compflow::USD_COMP > const & wellElemCompFrac = subRegion.getField< well::globalCompFraction >(); - arrayView1d< real64 const > const & wellElemGravCoef = subRegion.getField< well::gravityCoefficient >(); - - // get the element region, subregion, index - arrayView1d< localIndex const > const resElementRegion = perforationData.getField< perforation::reservoirElementRegion >(); - arrayView1d< localIndex const > const resElementSubRegion = perforationData.getField< perforation::reservoirElementSubRegion >(); - arrayView1d< localIndex const > const resElementIndex = perforationData.getField< perforation::reservoirElementIndex >(); - - arrayView1d< real64 const > const & perfGravCoef = perforationData.getField< fields::well::gravityCoefficient >(); - arrayView1d< integer const > const & perfStatus = perforationData.getField< fields::perforation::perforationStatus >(); - - // 1) Loop over all perforations to compute an average mixture density and component fraction - // 2) Initialize the reference pressure - // 3) Estimate the pressures in the well elements using the average density - compositionalMultiphaseWellKernels:: - PresTempCompFracInitializationKernel:: - launch( perforationData.size(), - subRegion.size(), - numComp, - numPhase, - wellControls, - 0.0, // initialization done at t = 0 - resCompFlowAccessors.get( flow::pressure{} ), - resCompFlowAccessors.get( flow::temperature{} ), - resCompFlowAccessors.get( flow::globalCompDensity{} ), - resCompFlowAccessors.get( flow::phaseVolumeFraction{} ), - resMultiFluidAccessors.get( fields::multifluid::phaseMassDensity{} ), - resElementRegion, - resElementSubRegion, - resElementIndex, - perfGravCoef, - perfStatus, - wellElemGravCoef, - wellElemPressure, - wellElemTemp, - wellElemCompFrac ); - - // get well secondary variables on well elements - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - MultiFluidBase & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); - arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const & wellElemPhaseDens = fluid.phaseDensity(); - arrayView2d< real64 const, constitutive::multifluid::USD_FLUID > const & wellElemTotalDens = fluid.totalDensity(); + } ); +} - // 4) Back calculate component densities - constitutive::constitutiveUpdatePassThru( fluid, [&] ( auto & castedFluid ) - { - typename TYPEOFREF( castedFluid ) ::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); - - thermalCompositionalMultiphaseBaseKernels:: - FluidUpdateKernel:: - launch< serialPolicy >( subRegion.size(), - fluidWrapper, - wellElemPressure, - wellElemTemp, - wellElemCompFrac ); - } ); +void CompositionalMultiphaseWell::assembleWellFluxTerms( real64 const & time, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + GEOS_MARK_FUNCTION; + GEOS_UNUSED_VAR( time ); - compositionalMultiphaseWellKernels:: - CompDensInitializationKernel::launch( subRegion.size(), - numComp, - wellElemCompFrac, - wellElemTotalDens, - wellElemCompDens ); + BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags; + if( m_useTotalMassEquation ) + kernelFlags.set( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ); - // 5) Recompute the pressure-dependent properties - updateSubRegionState( subRegion ); + string const wellDofKey = dofManager.getKey( wellElementDofName()); + + WellControls const & well_controls = getWellControls( subRegion ); + if( well_controls.isWellOpen( ) && !m_keepVariablesConstantDuringInitStep ) + { + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString()); + MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + int numComponents = fluid.numFluidComponents(); + + if( isThermal() ) + { + thermalCompositionalMultiphaseWellKernels:: + FaceBasedAssemblyKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( numComponents, + dt, + dofManager.rankOffset(), + kernelFlags, + wellDofKey, + well_controls, + subRegion, + fluid, + localMatrix, + localRhs ); + } + else + { + compositionalMultiphaseWellKernels:: + FaceBasedAssemblyKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( numComponents, + dt, + dofManager.rankOffset(), + kernelFlags, + wellDofKey, + well_controls, + subRegion, + localMatrix, + localRhs ); + } + } - // 6) Estimate the well rates - // TODO: initialize rates using perforation rates - compositionalMultiphaseWellKernels:: - RateInitializationKernel:: - launch( subRegion.size(), - m_targetPhaseIndex, - wellControls, - time_n, // initialization done at time_n - wellElemPhaseDens, - wellElemTotalDens, - connRate ); - } - } ); - } ); } void CompositionalMultiphaseWell::assembleFluxTerms( real64 const & time, @@ -1190,43 +1586,9 @@ void CompositionalMultiphaseWell::assembleFluxTerms( real64 const & time, [&]( localIndex const, WellElementSubRegion & subRegion ) { - WellControls const & well_controls = getWellControls( subRegion ); - if( well_controls.getWellStatus() == WellControls::Status::OPEN && !m_keepVariablesConstantDuringInitStep ) - { - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString()); - MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); - int const numComponents = fluid.numFluidComponents(); - if( isThermal() ) - { - thermalCompositionalMultiphaseWellKernels:: - FaceBasedAssemblyKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( numComponents, - dt, - dofManager.rankOffset(), - kernelFlags, - wellDofKey, - well_controls, - subRegion, - fluid, - localMatrix, - localRhs ); - } - else - { - compositionalMultiphaseWellKernels:: - FaceBasedAssemblyKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( numComponents, - dt, - dofManager.rankOffset(), - kernelFlags, - wellDofKey, - well_controls, - subRegion, - localMatrix, - localRhs ); - } - } + assembleWellFluxTerms( time, dt, subRegion, dofManager, localMatrix, localRhs ); + } ); } ); @@ -1256,106 +1618,230 @@ void CompositionalMultiphaseWell::assembleAccumulationTerms( real64 const & time [&]( localIndex const, WellElementSubRegion & subRegion ) { - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString()); - MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); - integer const numPhases = fluid.numFluidPhases(); - integer const numComponents = fluid.numFluidComponents(); - WellControls const & wellControls = getWellControls( subRegion ); - if( wellControls.getWellStatus() == WellControls::Status::OPEN && !m_keepVariablesConstantDuringInitStep ) - { - if( isThermal() ) - { - thermalCompositionalMultiphaseWellKernels:: - ElementBasedAssemblyKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( numComponents, - numPhases, - wellControls.isProducer(), - dofManager.rankOffset(), - kernelFlags, - wellDofKey, - subRegion, - fluid, - localMatrix, - localRhs ); - } - else - { - compositionalMultiphaseWellKernels:: - ElementBasedAssemblyKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( numComponents, - numPhases, - wellControls.isProducer(), - dofManager.rankOffset(), - kernelFlags, - wellDofKey, - subRegion, - fluid, - localMatrix, - localRhs ); - } - // get the degrees of freedom and ghosting info - arrayView1d< globalIndex const > const & wellElemDofNumber = - subRegion.getReference< array1d< globalIndex > >( wellDofKey ); - arrayView1d< integer const > const wellElemGhostRank = subRegion.ghostRank(); - arrayView1d< integer const > const elemStatus = subRegion.getLocalWellElementStatus(); - arrayView1d< real64 > const mixConnRate = subRegion.getField< fields::well::mixtureConnectionRate >(); - localIndex rank_offset = dofManager.rankOffset(); - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) + assembleWellAccumulationTerms( time, dt, subRegion, dofManager, localMatrix, localRhs ); + } ); + } ); + + +} + +void CompositionalMultiphaseWell::assembleWellAccumulationTerms( real64 const & time, + real64 const & dt, + WellElementSubRegion & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + 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() ); + + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString()); + MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + integer const numPhases = fluid.numFluidPhases(); + integer const numComponents = fluid.numFluidComponents(); + WellControls const & wellControls = getWellControls( subRegion ); + if( wellControls.getWellStatus() == WellControls::Status::OPEN && !m_keepVariablesConstantDuringInitStep ) + { + if( isThermal() ) + { + + thermalCompositionalMultiphaseWellKernels:: + ElementBasedAssemblyKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( numComponents, + numPhases, + wellControls.isProducer(), + dofManager.rankOffset(), + kernelFlags, + wellDofKey, + subRegion, + fluid, + localMatrix, + localRhs ); + } + else + { + compositionalMultiphaseWellKernels:: + ElementBasedAssemblyKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( numComponents, + numPhases, + wellControls.isProducer(), + dofManager.rankOffset(), + kernelFlags, + wellDofKey, + subRegion, + fluid, + localMatrix, + localRhs ); + } + } + else + { +//wellControls.setWellOpen(false); +// get the degrees of freedom and ghosting info + // get the degrees of freedom and ghosting info + arrayView1d< globalIndex const > const & wellElemDofNumber = + subRegion.getReference< array1d< globalIndex > >( wellDofKey ); + arrayView1d< integer const > const wellElemGhostRank = subRegion.ghostRank(); + arrayView1d< integer const > const elemStatus = subRegion.getLocalWellElementStatus(); + arrayView1d< real64 > mixConnRate = subRegion.getField< fields::well::mixtureConnectionRate >(); + localIndex rank_offset = dofManager.rankOffset(); + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + if( wellElemGhostRank[ei] < 0 ) + { + if( elemStatus[ei]==WellElementSubRegion::WellElemStatus::CLOSED ) { - if( wellElemGhostRank[ei] < 0 ) + mixConnRate[ei] = 0.0; + globalIndex const dofIndex = wellElemDofNumber[ei]; + localIndex const localRow = dofIndex - rank_offset; + + real64 const unity = 1.0; + for( integer i=0; i < m_numDofPerWellElement; i++ ) { - if( elemStatus[ei]==WellElementSubRegion::WellElemStatus::CLOSED ) - { - mixConnRate[ei] = 0.0; - globalIndex const dofIndex = wellElemDofNumber[ei]; - localIndex const localRow = dofIndex - rank_offset; - - real64 const unity = 1.0; - for( integer i=0; i < m_numDofPerWellElement; i++ ) - { - globalIndex const rindex = localRow+i; - globalIndex const cindex =dofIndex + i; - localMatrix.template addToRow< serialAtomic >( rindex, - &cindex, - &unity, - 1 ); - localRhs[rindex] = 0.0; - } - } + globalIndex const rindex = localRow+i; + globalIndex const cindex =dofIndex + i; + localMatrix.template addToRow< serialAtomic >( rindex, + &cindex, + &unity, + 1 ); + localRhs[rindex] = 0.0; } - } ); + } } - else + } ); + } + + + +} + + +real64 +CompositionalMultiphaseWell::calculateWellResidualNorm( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs ) +{ + GEOS_MARK_FUNCTION; + integer numNorm = 1; // mass balance + array1d< real64 > localResidualNorm; + array1d< real64 > localResidualNormalizer; + + if( isThermal() ) + { + numNorm = 2; // mass balance and energy balance + } + localResidualNorm.resize( numNorm ); + localResidualNormalizer.resize( numNorm ); + + + globalIndex const rankOffset = dofManager.rankOffset(); + string const wellDofKey = dofManager.getKey( wellElementDofName() ); + + + + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); + + WellControls const & wellControls = getWellControls( subRegion ); + + if( wellControls.isWellOpen( ) ) + { + // step 1: compute the norm in the subRegion + if( isThermal() ) + { + real64 subRegionResidualNorm[2]{}; + + thermalCompositionalMultiphaseWellKernels::ResidualNormKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_numComponents, + m_targetPhaseIndex, + rankOffset, + wellDofKey, + localRhs, + subRegion, + fluid, + wellControls, + time_n, + dt, + m_nonlinearSolverParameters.m_minNormalizer, + subRegionResidualNorm ); + // step 2: reduction across meshBodies/regions/subRegions + + for( integer i=0; i const & wellElemDofNumber = - subRegion.getReference< array1d< globalIndex > >( wellDofKey ); - arrayView1d< integer const > const & wellElemGhostRank = subRegion.ghostRank(); - localIndex rank_offset = dofManager.rankOffset(); - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) + if( subRegionResidualNorm[i] > localResidualNorm[i] ) { - if( wellElemGhostRank[ei] < 0 ) - { - globalIndex const dofIndex = wellElemDofNumber[ei]; - localIndex const localRow = dofIndex - rank_offset; + localResidualNorm[i] = subRegionResidualNorm[i]; + } + } - real64 unity = 1.0; - for( integer i=0; i < m_numDofPerWellElement; i++ ) - { - globalIndex const rindex = localRow+i; - globalIndex const cindex =dofIndex + i; - localMatrix.template addToRow< serialAtomic >( rindex, - &cindex, - &unity, - 1 ); - localRhs[rindex] = 0.0; - } - } - } ); + } + else + { + real64 subRegionResidualNorm[1]{}; + compositionalMultiphaseWellKernels::ResidualNormKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_numComponents, + numDofPerWellElement(), + m_targetPhaseIndex, + rankOffset, + wellDofKey, + localRhs, + subRegion, + fluid, + wellControls, + time_n, + dt, + m_nonlinearSolverParameters.m_minNormalizer, + subRegionResidualNorm ); + + + + // step 2: reduction across meshBodies/regions/subRegions + + if( subRegionResidualNorm[0] > localResidualNorm[0] ) + { + localResidualNorm[0] = subRegionResidualNorm[0]; } - } ); // forElementSubRegions - } ); // forDiscretizationOnMeshTargets + } + } + else + { + for( integer i=0; i >( m_numComponents, - m_targetPhaseIndex, - rankOffset, - wellDofKey, - localRhs, - subRegion, - fluid, - wellControls, - time_n, - dt, - m_nonlinearSolverParameters.m_minNormalizer, - subRegionResidualNorm ); - // step 2: reduction across meshBodies/regions/subRegions + thermalCompositionalMultiphaseWellKernels::ResidualNormKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_numComponents, + m_targetPhaseIndex, + rankOffset, + wellDofKey, + localRhs, + subRegion, + fluid, + wellControls, + time_n, + dt, + m_nonlinearSolverParameters.m_minNormalizer, + subRegionResidualNorm ); + // step 2: reduction across meshBodies/regions/subRegions - for( integer i=0; i localResidualNorm[i] ) + for( integer i=0; i localResidualNorm[i] ) + { + localResidualNorm[i] = subRegionResidualNorm[i]; + } } - } - } - else - { - real64 subRegionResidualNorm[1]{}; - compositionalMultiphaseWellKernels::ResidualNormKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( m_numComponents, - numDofPerWellElement(), - m_targetPhaseIndex, - rankOffset, - wellDofKey, - localRhs, - subRegion, - fluid, - wellControls, - time_n, - dt, - m_nonlinearSolverParameters.m_minNormalizer, - subRegionResidualNorm ); + } + else + { + real64 subRegionResidualNorm[1]{}; + compositionalMultiphaseWellKernels::ResidualNormKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_numComponents, + numDofPerWellElement(), + m_targetPhaseIndex, + rankOffset, + wellDofKey, + localRhs, + subRegion, + fluid, + wellControls, + time_n, + dt, + m_nonlinearSolverParameters.m_minNormalizer, + subRegionResidualNorm ); - // step 2: reduction across meshBodies/regions/subRegions + // step 2: reduction across meshBodies/regions/subRegions - if( subRegionResidualNorm[0] > localResidualNorm[0] ) + if( subRegionResidualNorm[0] > localResidualNorm[0] ) + { + localResidualNorm[0] = subRegionResidualNorm[0]; + } + } + } + else + { + for( integer i=0; i const & localSolution ) +{ + GEOS_MARK_FUNCTION; + + string const wellDofKey = dofManager.getKey( wellElementDofName() ); + + real64 scalingFactor = 1.0; + real64 maxDeltaPres = 0.0, maxDeltaCompDens = 0.0, maxDeltaTemp = 0.0; + real64 minPresScalingFactor = 1.0, minCompDensScalingFactor = 1.0, minTempScalingFactor = 1.0; + + arrayView1d< real64 const > const pressure = subRegion.getField< fields::well::pressure >(); + arrayView1d< real64 const > const temperature = subRegion.getField< fields::well::temperature >(); + arrayView2d< real64 const, compflow::USD_COMP > const compDens = subRegion.getField< fields::well::globalCompDensity >(); + arrayView1d< real64 > pressureScalingFactor = subRegion.getField< fields::well::pressureScalingFactor >(); + arrayView1d< real64 > temperatureScalingFactor = subRegion.getField< fields::well::temperatureScalingFactor >(); + arrayView1d< real64 > compDensScalingFactor = subRegion.getField< fields::well::globalCompDensityScalingFactor >(); + const integer temperatureOffset = m_numComponents+2; + auto const subRegionData = + m_isThermal + ? thermalCompositionalMultiphaseBaseKernels:: + SolutionScalingKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_maxRelativePresChange, + m_maxAbsolutePresChange, + m_maxRelativeTempChange, + m_maxCompFracChange, + m_maxRelativeCompDensChange, + pressure, + temperature, + compDens, + pressureScalingFactor, + compDensScalingFactor, + temperatureScalingFactor, + dofManager.rankOffset(), + m_numComponents, + wellDofKey, + subRegion, + localSolution, + temperatureOffset ) + : isothermalCompositionalMultiphaseBaseKernels:: + SolutionScalingKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_maxRelativePresChange, + m_maxAbsolutePresChange, + m_maxCompFracChange, + m_maxRelativeCompDensChange, + pressure, + compDens, + pressureScalingFactor, + compDensScalingFactor, + dofManager.rankOffset(), + m_numComponents, + wellDofKey, + subRegion, + localSolution ); + + + scalingFactor = std::min( subRegionData.localMinVal, scalingFactor ); + + maxDeltaPres = std::max( maxDeltaPres, subRegionData.localMaxDeltaPres ); + maxDeltaCompDens = std::max( maxDeltaCompDens, subRegionData.localMaxDeltaCompDens ); + maxDeltaTemp = std::max( maxDeltaTemp, subRegionData.localMaxDeltaTemp ); + minPresScalingFactor = std::min( minPresScalingFactor, subRegionData.localMinPresScalingFactor ); + minCompDensScalingFactor = std::min( minCompDensScalingFactor, subRegionData.localMinCompDensScalingFactor ); + minTempScalingFactor = std::min( minTempScalingFactor, subRegionData.localMinTempScalingFactor ); + + + scalingFactor = MpiWrapper::min( scalingFactor ); + maxDeltaPres = MpiWrapper::max( maxDeltaPres ); + maxDeltaCompDens = MpiWrapper::max( maxDeltaCompDens ); + minPresScalingFactor = MpiWrapper::min( minPresScalingFactor ); + minCompDensScalingFactor = MpiWrapper::min( minCompDensScalingFactor ); + + string const massUnit = m_useMass ? "kg/m3" : "mol/m3"; + GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, + GEOS_FMT( " {}: Max well pressure change: {} Pa (before scaling)", + getName(), GEOS_FMT( "{:.{}f}", maxDeltaPres, 3 ) ) ); + GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, + GEOS_FMT( " {}: Max well component density change: {} {} (before scaling)", + getName(), GEOS_FMT( "{:.{}f}", maxDeltaCompDens, 3 ), massUnit ) ); + + if( m_isThermal ) + { + maxDeltaTemp = MpiWrapper::max( maxDeltaTemp ); + minTempScalingFactor = MpiWrapper::min( minTempScalingFactor ); + GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, + GEOS_FMT( " {}: Max well temperature change: {} K (before scaling)", + getName(), GEOS_FMT( "{:.{}f}", maxDeltaTemp, 3 ) ) ); + } + + + GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, + GEOS_FMT( " {}: Min well pressure scaling factor: {}", + getName(), minPresScalingFactor ) ); + GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, + GEOS_FMT( " {}: Min well component density scaling factor: {}", + getName(), minCompDensScalingFactor ) ); + if( m_isThermal ) + { + GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, + GEOS_FMT( " {}: Min well temperature scaling factor: {}", + getName(), minTempScalingFactor ) ); + } + + + return LvArray::math::max( scalingFactor, m_minScalingFactor ); + +} + real64 CompositionalMultiphaseWell::scalingForSystemSolution( DomainPartition & domain, DofManager const & dofManager, @@ -1608,88 +2214,83 @@ CompositionalMultiphaseWell::scalingForSystemSolution( DomainPartition & domain, } bool -CompositionalMultiphaseWell::checkSystemSolution( DomainPartition & domain, - DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution, - real64 const scalingFactor ) +CompositionalMultiphaseWell::checkWellSystemSolution( ElementSubRegionBase & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor ) { GEOS_MARK_FUNCTION; string const wellDofKey = dofManager.getKey( wellElementDofName() ); integer localCheck = 1; + + real64 minPres = 0.0, minDens = 0.0, minTotalDens = 0.0; integer numNegPres = 0, numNegDens = 0, numNegTotalDens = 0; - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - //integer const m_allowCompDensChopping(true); - integer const m_allowNegativePressure( false ); - compositionalMultiphaseUtilities::ScalingType const m_scalingType( compositionalMultiphaseUtilities::ScalingType::Global ); - arrayView1d< real64 const > const pressure = - subRegion.getField< well::pressure >(); - arrayView1d< real64 const > const temperature = - subRegion.getField< well::temperature >(); - arrayView2d< real64 const, compflow::USD_COMP > const compDens = - subRegion.getField< well::globalCompDensity >(); - arrayView1d< real64 > pressureScalingFactor = subRegion.getField< well::pressureScalingFactor >(); - arrayView1d< real64 > temperatureScalingFactor = subRegion.getField< well::temperatureScalingFactor >(); - arrayView1d< real64 > compDensScalingFactor = subRegion.getField< well::globalCompDensityScalingFactor >(); - - // check that pressure and component densities are non-negative - // for thermal, check that temperature is above 273.15 K - const integer temperatureOffset = m_numComponents+2; - auto const subRegionData = - m_isThermal + const std::string wellName = subRegion.getName(); + + //integer const m_allowCompDensChopping(true); + integer const m_allowNegativePressure( false ); + compositionalMultiphaseUtilities::ScalingType const m_scalingType( compositionalMultiphaseUtilities::ScalingType::Global ); + arrayView1d< real64 const > const pressure = + subRegion.getField< fields::well::pressure >(); + arrayView1d< real64 const > const temperature = + subRegion.getField< fields::well::temperature >(); + arrayView2d< real64 const, compflow::USD_COMP > const compDens = + subRegion.getField< fields::well::globalCompDensity >(); + arrayView1d< real64 > pressureScalingFactor = subRegion.getField< fields::well::pressureScalingFactor >(); + arrayView1d< real64 > temperatureScalingFactor = subRegion.getField< fields::well::temperatureScalingFactor >(); + arrayView1d< real64 > compDensScalingFactor = subRegion.getField< fields::well::globalCompDensityScalingFactor >(); + + // check that pressure and component densities are non-negative + // for thermal, check that temperature is above 273.15 K + const integer temperatureOffset = m_numComponents+2; + auto const subRegionData = + m_isThermal ? thermalCompositionalMultiphaseBaseKernels:: - SolutionCheckKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( m_allowCompDensChopping, - m_allowNegativePressure, - m_scalingType, - scalingFactor, - pressure, - temperature, - compDens, - pressureScalingFactor, - temperatureScalingFactor, - compDensScalingFactor, - dofManager.rankOffset(), - m_numComponents, - wellDofKey, - subRegion, - localSolution, - temperatureOffset ) + SolutionCheckKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_allowCompDensChopping, + m_allowNegativePressure, + m_scalingType, + scalingFactor, + pressure, + temperature, + compDens, + pressureScalingFactor, + temperatureScalingFactor, + compDensScalingFactor, + dofManager.rankOffset(), + m_numComponents, + wellDofKey, + subRegion, + localSolution, + temperatureOffset ) : isothermalCompositionalMultiphaseBaseKernels:: - SolutionCheckKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( m_allowCompDensChopping, - m_allowNegativePressure, - m_scalingType, - scalingFactor, - pressure, - compDens, - pressureScalingFactor, - compDensScalingFactor, - dofManager.rankOffset(), - m_numComponents, - wellDofKey, - subRegion, - localSolution ); + SolutionCheckKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_allowCompDensChopping, + m_allowNegativePressure, + m_scalingType, + scalingFactor, + pressure, + compDens, + pressureScalingFactor, + compDensScalingFactor, + dofManager.rankOffset(), + m_numComponents, + wellDofKey, + subRegion, + localSolution ); - localCheck = std::min( localCheck, subRegionData.localMinVal ); + localCheck = std::min( localCheck, subRegionData.localMinVal ); + + minPres = std::min( minPres, subRegionData.localMinPres ); + minDens = std::min( minDens, subRegionData.localMinDens ); + minTotalDens = std::min( minTotalDens, subRegionData.localMinTotalDens ); + numNegPres += subRegionData.localNumNegPressures; + numNegDens += subRegionData.localNumNegDens; + numNegTotalDens += subRegionData.localNumNegTotalDens; - minPres = std::min( minPres, subRegionData.localMinPres ); - minDens = std::min( minDens, subRegionData.localMinDens ); - minTotalDens = std::min( minTotalDens, subRegionData.localMinTotalDens ); - numNegPres += subRegionData.localNumNegPressures; - numNegDens += subRegionData.localNumNegDens; - numNegTotalDens += subRegionData.localNumNegTotalDens; - } ); - } ); minPres = MpiWrapper::min( minPres ); minDens = MpiWrapper::min( minDens ); @@ -1701,93 +2302,130 @@ CompositionalMultiphaseWell::checkSystemSolution( DomainPartition & domain, if( numNegPres > 0 ) GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, GEOS_FMT( " {}: Number of negative well pressure values: {}, minimum value: {} Pa", - getName(), numNegPres, fmt::format( "{:.{}f}", minPres, 3 ) ) ); + subRegion.getName(), numNegPres, fmt::format( "{:.{}f}", minPres, 3 ) ) ); string const massUnit = m_useMass ? "kg/m3" : "mol/m3"; if( numNegDens > 0 ) GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, GEOS_FMT( " {}: Number of negative well component density values: {}, minimum value: {} {} ", - getName(), numNegDens, fmt::format( "{:.{}f}", minDens, 3 ), massUnit ) ); + subRegion.getName(), numNegDens, fmt::format( "{:.{}f}", minDens, 3 ), massUnit ) ); if( minTotalDens > 0 ) GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, GEOS_FMT( " {}: Number of negative total well density values: {}, minimum value: {} {} ", - getName(), minTotalDens, fmt::format( "{:.{}f}", minDens, 3 ), massUnit ) ); + subRegion.getName(), minTotalDens, fmt::format( "{:.{}f}", minDens, 3 ), massUnit ) ); + + return MpiWrapper::min( localCheck ); } -void CompositionalMultiphaseWell::computePerforationRates( real64 const & time_n, - real64 const & GEOS_UNUSED_PARAM( dt ), - DomainPartition & domain ) +bool +CompositionalMultiphaseWell::checkSystemSolution( DomainPartition & domain, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor ) { GEOS_MARK_FUNCTION; - GEOS_UNUSED_VAR( time_n ); - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) + string const wellDofKey = dofManager.getKey( wellElementDofName() ); + integer globalCheck = 1; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + integer localCheck = checkWellSystemSolution( subRegion, dofManager, localSolution, scalingFactor ); + globalCheck = MpiWrapper::min( localCheck ); + } ); + } ); + return globalCheck; +} - // TODO: change the way we access the flowSolver here - CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); - ElementRegionManager & elemManager = mesh.getElemManager(); +void +CompositionalMultiphaseWell::applyWellSystemSolution( DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor, + real64 const dt, + DomainPartition & domain, + MeshLevel & mesh, + WellElementSubRegion & subRegion ) +{ + + GEOS_UNUSED_VAR( domain ); + DofManager::CompMask pressureMask( m_numDofPerWellElement, 0, 1 ); + DofManager::CompMask componentMask( m_numDofPerWellElement, 1, numFluidComponents()+1 ); + DofManager::CompMask connRateMask( m_numDofPerWellElement, numFluidComponents()+1, numFluidComponents()+2 ); + GEOS_UNUSED_VAR( dt ); + // update all the fields using the global damping coefficients + dofManager.addVectorToField( localSolution, + wellElementDofName(), + fields::well::pressure::key(), + scalingFactor, + pressureMask ); + + dofManager.addVectorToField( localSolution, + wellElementDofName(), + fields::well::globalCompDensity::key(), + scalingFactor, + componentMask ); - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, - WellElementSubRegion & subRegion ) + dofManager.addVectorToField( localSolution, + wellElementDofName(), + fields::well::mixtureConnectionRate::key(), + scalingFactor, + connRateMask ); + arrayView1d< real64 const > const & temp =subRegion.getField< fields::well::temperature >(); + if( isThermal() ) + { + DofManager::CompMask temperatureMask( m_numDofPerWellElement, numFluidComponents()+2, numFluidComponents()+3 ); + + for( integer i=0; i( viewKeyStruct::fluidNamesString() ); - MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); - bool const isThermal = fluid.isThermal(); + std::cout << " bu temp i "<< i << " " << temp[i] << std::endl; + } + dofManager.addVectorToField( localSolution, + wellElementDofName(), + fields::well::temperature::key(), + scalingFactor, + temperatureMask ); - if( isThermal ) - { - thermalPerforationFluxKernels:: - PerforationFluxKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( m_numComponents, - m_numPhases, - flowSolver.getName(), - perforationData, - subRegion, - fluid, - elemManager, - wellControls.isInjector(), - wellControls.isCrossflowEnabled() ); - } - else - { - isothermalPerforationFluxKernels:: - PerforationFluxKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( m_numComponents, - m_numPhases, - flowSolver.getName(), - perforationData, - subRegion, - elemManager, - wellControls.isInjector(), - wellControls.isCrossflowEnabled() ); - } - } - else - { - // Zero completion flow rate - arrayView2d< real64 > const compPerfRate = perforationData->getField< well::compPerforationRate >(); - for( integer iperf=0; iperfsize(); iperf++ ) - { - for( integer ic = 0; ic < m_numComponents; ++ic ) - { - compPerfRate[iperf][ic] = 0.0; - } - } - } - } ); + } - } ); +#if 1 + // if component density chopping is allowed, some component densities may be negative after the update + // these negative component densities are set to zero in this function + if( m_allowCompDensChopping ) + { + chopNegativeDensities( subRegion ); + } +#endif -} + // synchronize + FieldIdentifiers fieldsToBeSync; + if( isThermal() ) + { + fieldsToBeSync.addElementFields( { fields::well::pressure::key(), + fields::well::globalCompDensity::key(), + fields::well::mixtureConnectionRate::key(), + fields::well::temperature::key() }, + getTargetRegionNames() ); + } + else + { + fieldsToBeSync.addElementFields( { fields::well::pressure::key(), + fields::well::globalCompDensity::key(), + fields::well::mixtureConnectionRate::key() }, + getTargetRegionNames() ); + } + CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, + mesh, + domain.getNeighbors(), + true ); +} void CompositionalMultiphaseWell::applySystemSolution( DofManager const & dofManager, @@ -1855,18 +2493,59 @@ CompositionalMultiphaseWell::applySystemSolution( DofManager const & dofManager, } else { - fieldsToBeSync.addElementFields( { well::pressure::key(), - well::globalCompDensity::key(), - well::mixtureConnectionRate::key() }, - regionNames ); + fieldsToBeSync.addElementFields( { well::pressure::key(), + well::globalCompDensity::key(), + well::mixtureConnectionRate::key() }, + regionNames ); + } + CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, + mesh, + domain.getNeighbors(), + true ); + } ); + + +} + +void CompositionalMultiphaseWell::chopNegativeDensities( WellElementSubRegion & subRegion ) +{ + integer const numComp = m_numComponents; + + + arrayView1d< integer const > const & wellElemGhostRank = subRegion.ghostRank(); + + arrayView2d< real64, compflow::USD_COMP > const & wellElemCompDens = + subRegion.getField< fields::well::globalCompDensity >(); + + //arrayView2d< real64, compflow::USD_COMP > const & wellElemCompDens_n = + // subRegion.getField< fields::well::globalCompDensity_n >(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) + { + /* + for( integer ic = 0; ic < numComp; ++ic ) + { + if( iwelem == 65 ) + { + std::cout << "tjb dens " << iwelem << " " << ic << " " << wellElemCompDens[iwelem][ic] << " " << wellElemCompDens_n[iwelem][ic] << + std::endl; + } + } + */ + if( wellElemGhostRank[iwelem] < 0 ) + { + for( integer ic = 0; ic < numComp; ++ic ) + { + // we allowed for some densities to be slightly negative in CheckSystemSolution + // if the new density is negative, chop back to zero + if( wellElemCompDens[iwelem][ic] < 0 ) + { + wellElemCompDens[iwelem][ic] = 0.0; + } + } } - CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, - mesh, - domain.getNeighbors(), - true ); } ); - } void CompositionalMultiphaseWell::chopNegativeDensities( DomainPartition & domain ) @@ -1960,15 +2639,179 @@ void CompositionalMultiphaseWell::resetStateToBeginningOfStep( DomainPartition & } ); } +void CompositionalMultiphaseWell::assembleWellConstraintTerms( real64 const & time_n, + real64 const & GEOS_UNUSED_PARAM( dt ), + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + GEOS_MARK_FUNCTION; + + + // the rank that owns the reference well element is responsible for the calculations below. + if( !subRegion.isLocallyOwned() ) + { + return; + } + WellControls & wellControls = getWellControls( subRegion ); + + { + wellControls.forSubGroups< BHPConstraint, PhaseConstraint, MassConstraint, TotalVolConstraint, LiquidConstraint >( [&]( auto & constraint ) + { + using ConstraintType = std::remove_reference_t< decltype(constraint) >; + if( constraint.getName() == wellControls.getCurrentConstraint()->getName()) + { + // found limiting constraint + + // fluid data + constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); + integer isThermal = fluidSeparator.isThermal(); + integer const numComp = fluidSeparator.numFluidComponents(); + geos::internal::kernelLaunchSelectorCompThermSwitch( numComp, isThermal, [&] ( auto NC, auto ISTHERMAL ) + { + integer constexpr NUM_COMP = NC(); + integer constexpr IS_THERMAL = ISTHERMAL(); + + wellConstraintKernels::ConstraintHelper< NUM_COMP, IS_THERMAL, ConstraintType >::assembleConstraintEquation( time_n, + wellControls, + constraint, + subRegion, + dofManager.getKey( wellElementDofName() ), + dofManager.rankOffset(), + localMatrix, + localRhs ); + } ); + } + + } ); + } + +} + + +void CompositionalMultiphaseWell::assembleWellPressureRelations( real64 const & time_n, + real64 const & GEOS_UNUSED_PARAM( dt ), + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + GEOS_MARK_FUNCTION; + + + WellControls & wellControls = getWellControls( subRegion ); + + if( wellControls.isWellOpen( ) && !m_keepVariablesConstantDuringInitStep ) + { + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + bool const isThermal = fluid.isThermal(); + // get the degrees of freedom, depth info, next welem index + string const wellDofKey = dofManager.getKey( wellElementDofName() ); + arrayView1d< globalIndex const > const & wellElemDofNumber = + subRegion.getReference< array1d< globalIndex > >( wellDofKey ); + arrayView1d< real64 const > const & wellElemGravCoef = + subRegion.getField< well::gravityCoefficient >(); + arrayView1d< localIndex const > const & nextWellElemIndex = + subRegion.getReference< array1d< localIndex > >( WellElementSubRegion::viewKeyStruct::nextWellElementIndexString() ); + + // get primary variables on well elements + arrayView1d< real64 const > const & wellElemPres = + subRegion.getField< well::pressure >(); + + // get total mass density on well elements (for potential calculations) + arrayView1d< real64 const > const & wellElemTotalMassDens = + subRegion.getField< well::totalMassDensity >(); + arrayView2d< real64 const, compflow::USD_FLUID_DC > const & dWellElemTotalMassDens = + subRegion.getField< well::dTotalMassDensity >(); + + // segment status + arrayView1d< integer const > const elemStatus =subRegion.getLocalWellElementStatus(); + + bool controlHasSwitched = false; + isothermalCompositionalMultiphaseBaseKernels:: + KernelLaunchSelectorCompTherm< compositionalMultiphaseWellKernels::PressureRelationKernel > + ( numFluidComponents(), + isThermal, + subRegion.size(), + dofManager.rankOffset(), + subRegion.isLocallyOwned(), + subRegion.getTopWellElementIndex(), + m_targetPhaseIndex, + wellControls, + time_n, // controls evaluated with BHP/rate of the beginning of step + elemStatus, + wellElemDofNumber, + wellElemGravCoef, + nextWellElemIndex, + wellElemPres, + wellElemTotalMassDens, + dWellElemTotalMassDens, + controlHasSwitched, + localMatrix, + localRhs ); + + if( controlHasSwitched ) + { + // TODO: move the switch logic into wellControls + // TODO: implement a more general switch when more then two constraints per well type are allowed + + if( wellControls.getControl() == WellControls::Control::BHP ) + { + if( wellControls.isProducer() ) + { + wellControls.switchToPhaseRateControl( wellControls.getTargetPhaseRate( time_n ) ); + GEOS_LOG_LEVEL_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( time_n ) ); + GEOS_LOG_LEVEL_RANK_0( logInfo::WellControl, + GEOS_FMT( "Control switch for well {} from BHP constraint to mass rate constraint", subRegion.getName()) ); + } + else + { + wellControls.switchToTotalRateControl( wellControls.getTargetTotalRate( time_n ) ); + GEOS_LOG_LEVEL_RANK_0( logInfo::WellControl, + GEOS_FMT( "Control switch for well {} from BHP constraint to total volumetric rate constraint", subRegion.getName()) ); + } + } + else + { + wellControls.switchToBHPControl( wellControls.getTargetBHP( time_n ) ); + GEOS_LOG_LEVEL_RANK_0( logInfo::WellControl, + GEOS_FMT( "Control switch for well {} from rate constraint to BHP constraint", subRegion.getName() ) ); + } + } + + // If a well is opened and then timestep is cut resulting in the well being shut, if the well is opened + // the well initialization code requires control type to by synced + integer owner = -1; + // Only subregion owner evaluates well control and control changes need to be broadcast to all ranks + if( subRegion.isLocallyOwned() ) + { + owner = MpiWrapper::commRank( MPI_COMM_GEOS ); + } + owner = MpiWrapper::max( owner ); + WellControls::Control wellControl = wellControls.getControl(); + MpiWrapper::broadcast( wellControl, owner ); + wellControls.setControl( wellControl ); + + } + +} + void CompositionalMultiphaseWell::assemblePressureRelations( real64 const & time_n, - real64 const & GEOS_UNUSED_PARAM( dt ), + real64 const & dt, DomainPartition const & domain, DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { GEOS_MARK_FUNCTION; - + GEOS_UNUSED_PARAM( dt ) forDiscretizationOnMeshTargets ( domain.getMeshBodies(), [&] ( string const &, MeshLevel const & mesh, string_array const & regionNames ) @@ -1981,109 +2824,57 @@ void CompositionalMultiphaseWell::assemblePressureRelations( real64 const & time WellElementSubRegion const & subRegion ) { - WellControls & wellControls = getWellControls( subRegion ); + assembleWellPressureRelations( time_n, dt, subRegion, dofManager, localMatrix, localRhs ); + } ); + } ); - if( wellControls.isWellOpen( ) && !m_keepVariablesConstantDuringInitStep ) - { - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); - bool const isThermal = fluid.isThermal(); - // get the degrees of freedom, depth info, next welem index - string const wellDofKey = dofManager.getKey( wellElementDofName() ); - arrayView1d< globalIndex const > const & wellElemDofNumber = - subRegion.getReference< array1d< globalIndex > >( wellDofKey ); - arrayView1d< real64 const > const & wellElemGravCoef = - subRegion.getField< well::gravityCoefficient >(); - arrayView1d< localIndex const > const & nextWellElemIndex = - subRegion.getReference< array1d< localIndex > >( WellElementSubRegion::viewKeyStruct::nextWellElementIndexString() ); - - // get primary variables on well elements - arrayView1d< real64 const > const & wellElemPres = - subRegion.getField< well::pressure >(); - - // get total mass density on well elements (for potential calculations) - arrayView1d< real64 const > const & wellElemTotalMassDens = - subRegion.getField< well::totalMassDensity >(); - arrayView2d< real64 const, compflow::USD_FLUID_DC > const & dWellElemTotalMassDens = - subRegion.getField< well::dTotalMassDensity >(); - - // segment status - arrayView1d< integer const > const elemStatus =subRegion.getLocalWellElementStatus(); - - bool controlHasSwitched = false; - isothermalCompositionalMultiphaseBaseKernels:: - KernelLaunchSelectorCompTherm< compositionalMultiphaseWellKernels::PressureRelationKernel > - ( numFluidComponents(), - isThermal, - subRegion.size(), - dofManager.rankOffset(), - subRegion.isLocallyOwned(), - subRegion.getTopWellElementIndex(), - m_targetPhaseIndex, - wellControls, - time_n, // controls evaluated with BHP/rate of the beginning of step - elemStatus, - wellElemDofNumber, - wellElemGravCoef, - nextWellElemIndex, - wellElemPres, - wellElemTotalMassDens, - dWellElemTotalMassDens, - controlHasSwitched, - localMatrix, - localRhs ); - - if( controlHasSwitched ) - { - // TODO: move the switch logic into wellControls - // TODO: implement a more general switch when more then two constraints per well type are allowed +} - if( wellControls.getControl() == WellControls::Control::BHP ) - { - if( wellControls.isProducer() ) - { - wellControls.switchToPhaseRateControl( wellControls.getTargetPhaseRate( time_n ) ); - GEOS_LOG_LEVEL_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( time_n ) ); - GEOS_LOG_LEVEL_RANK_0( logInfo::WellControl, - GEOS_FMT( "Control switch for well {} from BHP constraint to mass rate constraint", subRegion.getName()) ); - } - else - { - wellControls.switchToTotalRateControl( wellControls.getTargetTotalRate( time_n ) ); - GEOS_LOG_LEVEL_RANK_0( logInfo::WellControl, - GEOS_FMT( "Control switch for well {} from BHP constraint to total volumetric rate constraint", subRegion.getName()) ); - } - } - else - { - wellControls.switchToBHPControl( wellControls.getTargetBHP( time_n ) ); - GEOS_LOG_LEVEL_RANK_0( logInfo::WellControl, - GEOS_FMT( "Control switch for well {} from rate constraint to BHP constraint", subRegion.getName() ) ); - } - } +void CompositionalMultiphaseWell::saveState( WellElementSubRegion & subRegion ) +{ - // If a well is opened and then timestep is cut resulting in the well being shut, if the well is opened - // the well initialization code requires control type to by synced - integer owner = -1; - // Only subregion owner evaluates well control and control changes need to be broadcast to all ranks - if( subRegion.isLocallyOwned() ) - { - owner = MpiWrapper::commRank( MPI_COMM_GEOS ); - } - owner = MpiWrapper::max( owner ); - WellControls::Control wellControl = wellControls.getControl(); - MpiWrapper::broadcast( wellControl, owner ); - wellControls.setControl( wellControl ); - } + // get a reference to the primary variables on well elements + arrayView1d< real64 const > const & wellElemPressure = + subRegion.getField< fields::well::pressure >(); + arrayView2d< real64 const, compflow::USD_COMP > const & wellElemGlobalCompDensity = + subRegion.getField< fields::well::globalCompDensity >(); + arrayView1d< real64 const > const & wellElemTemperature = + subRegion.getField< fields::well::temperature >(); + + arrayView1d< real64 > const & wellElemPressure_n = + subRegion.getField< fields::well::pressure_n >(); + wellElemPressure_n.setValues< parallelDevicePolicy<> >( wellElemPressure ); + + if( isThermal() ) + { + + arrayView1d< real64 > const & wellElemTemperature_n = + subRegion.getField< fields::well::temperature_n >(); + wellElemTemperature_n.setValues< parallelDevicePolicy<> >( wellElemTemperature ); + } + + arrayView2d< real64, compflow::USD_COMP > const & wellElemGlobalCompDensity_n = + subRegion.getField< fields::well::globalCompDensity_n >(); + wellElemGlobalCompDensity_n.setValues< parallelDevicePolicy<> >( wellElemGlobalCompDensity ); + + arrayView1d< real64 const > const & connRate = + subRegion.getField< fields::well::mixtureConnectionRate >(); + arrayView1d< real64 > const & connRate_n = + subRegion.getField< fields::well::mixtureConnectionRate_n >(); + connRate_n.setValues< parallelDevicePolicy<> >( connRate ); + + arrayView2d< real64 const, compflow::USD_PHASE > const wellElemPhaseVolFrac = + subRegion.getField< fields::well::phaseVolumeFraction >(); + arrayView2d< real64, compflow::USD_PHASE > const wellElemPhaseVolFrac_n = + subRegion.getField< fields::well::phaseVolumeFraction_n >(); + wellElemPhaseVolFrac_n.setValues< parallelDevicePolicy<> >( wellElemPhaseVolFrac ); + + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + fluid.saveConvergedState(); + - } ); - } ); } void CompositionalMultiphaseWell::implicitStepSetup( real64 const & time_n, @@ -2313,5 +3104,477 @@ void CompositionalMultiphaseWell::printRates( real64 const & time_n, } ); } + +template< typename ... GROUPTYPES > +void CompositionalMultiphaseWell::selectLimitingConstraint( real64 const & time_n, + + integer const coupledIterationNumber, + + WellElementSubRegion & subRegion ) +{ + + WellControls & wellControls = getWellControls( subRegion ); + + bool useEstimator = coupledIterationNumber < wellControls.estimateSolution(); + if( useEstimator ) + { + + // find limiting constraint + WellConstraintBase * limitingConstraint = nullptr; + wellControls.forSubGroups< WellConstraintBase, GROUPTYPES... >( [&]( auto & constraint ) + { + //std::cout << "Use estimator " << useEstimator << " valuating constraint " << constraint.getName() << std::endl; + if( limitingConstraint != nullptr && constraint.isConstraintActive() ) + std::cout << " against constraint " << limitingConstraint->getName() << std::endl; + if( constraint.isConstraintActive() ) + { + if( limitingConstraint == nullptr || constraint.checkViolation( *limitingConstraint, time_n )) + { + limitingConstraint = &constraint; + + std::cout << "New limiting constraint " << constraint.getName() << std::endl; + + wellControls.setControl( static_cast< WellControls::Control >(limitingConstraint->getControl()) ); // tjb old + wellControls.setCurrentConstraint( limitingConstraint ); + } + } + } ); + + } + else + { + // Get current constraint + WellConstraintBase * limitingConstraint = nullptr; + wellControls.forSubGroups< WellConstraintBase, GROUPTYPES... >( [&]( auto & constraint ) + { + if( constraint.getName() == wellControls.getCurrentConstraint()->getName()) + { + limitingConstraint = &constraint; + // tjb. this is likely not needed. set in update state + constraint.setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); + constraint.setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( + CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); + constraint.setTotalVolumeRate ( wellControls.getReference< real64 >( + CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); + constraint.setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); + wellControls.setControl( static_cast< WellControls::Control >(limitingConstraint->getControl()) ); // tjb old + wellControls.setCurrentConstraint( limitingConstraint ); + } + } ); + + + + } +} + + +template< typename GROUPTYPE, typename ... GROUPTYPES > +void CompositionalMultiphaseWell::solveConstraint( real64 const & time_n, + real64 const & dt, + integer const cycleNumber, + integer const coupledIterationNumber, + DomainPartition & domain, + MeshLevel & mesh, + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion, + DofManager const & dofManager ) +{ + + WellControls & wellControls = getWellControls( subRegion ); + bool useEstimator = coupledIterationNumber < wellControls.estimateSolution(); + if( useEstimator ) + { + + wellControls.forSubGroups< GROUPTYPE, GROUPTYPES... >( [&]( auto & constraint ) + { + if( getLogLevel() > 4 ) + { + GEOS_LOG_RANK_0( "Well " << wellControls.getName() << " Evaluating constraint " << constraint.getName() << " value " << constraint.getConstraintValue( time_n ) << " active " << + constraint.isConstraintActive() ); + } + if( constraint.isConstraintActive() ) + { + wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old + wellControls.setCurrentConstraint( &constraint ); + // If a well is opened and then timestep is cut resulting in the well being shut, if the well is opened +// the well initialization code requires control type to by synced + integer owner = -1; +// Only subregion owner evaluates well control and control changes need to be broadcast to all ranks + if( subRegion.isLocallyOwned() ) + { + owner = MpiWrapper::commRank( MPI_COMM_GEOS ); + } + owner = MpiWrapper::max( owner ); + WellControls::Control wellControl = wellControls.getControl(); + MpiWrapper::broadcast( wellControl, owner ); + wellControls.setControl( wellControl ); + solveNonlinearSystem( time_n, + dt, + cycleNumber, + domain, + mesh, + elemManager, + subRegion, + dofManager ); + + // Store computed well quantities for this constraint + constraint.setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); + constraint.setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( + CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); + constraint.setTotalVolumeRate ( wellControls.getReference< real64 >( + CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); + constraint.setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); + if( getLogLevel() > 4 ) + { + GEOS_LOG_RANK_0( "Well " << wellControls.getName() << " aft solve Constraint rates " << constraint.getName() << " bhp " << constraint.bottomHolePressure() << " phaseVolRate " << + constraint.phaseVolumeRates() << " totalVolRate " << constraint.totalVolumeRate() << " massRate " << constraint.massRate()); + } + } + } ); + + } + +} + + +void CompositionalMultiphaseWell::solveConstraint( std::shared_ptr< WellConstraintBase > constraint, + real64 const & time_n, + real64 const & dt, + integer const cycleNumber, + integer const coupledIterationNumber, + DomainPartition & domain, + MeshLevel & mesh, + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion, + DofManager const & dofManager ) +{ + + WellControls & wellControls = getWellControls( subRegion ); + bool useEstimator = coupledIterationNumber < wellControls.estimateSolution(); + if( useEstimator ) + { + + if( getLogLevel() > 4 ) + { + GEOS_LOG_RANK_0( "Well " << wellControls.getName() << " Evaluating constraint " << constraint->getName() << " value " << constraint->getConstraintValue( time_n ) << " active " << + constraint->isConstraintActive() ); + } + if( constraint->isConstraintActive() ) + { + wellControls.setControl( static_cast< WellControls::Control >(constraint->getControl()) ); // tjb old + wellControls.setCurrentConstraint( constraint.get() ); + // If a well is opened and then timestep is cut resulting in the well being shut, if the well is opened +// the well initialization code requires control type to by synced + integer owner = -1; +// Only subregion owner evaluates well control and control changes need to be broadcast to all ranks + if( subRegion.isLocallyOwned() ) + { + owner = MpiWrapper::commRank( MPI_COMM_GEOS ); + } + owner = MpiWrapper::max( owner ); + WellControls::Control wellControl = wellControls.getControl(); + MpiWrapper::broadcast( wellControl, owner ); + wellControls.setControl( wellControl ); + solveNonlinearSystem( time_n, + dt, + cycleNumber, + domain, + mesh, + elemManager, + subRegion, + dofManager ); + + // Store computed well quantities for this constraint + constraint->setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); + constraint->setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( + CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); + constraint->setTotalVolumeRate ( wellControls.getReference< real64 >( + CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); + constraint->setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); + if( getLogLevel() > 4 ) + { + GEOS_LOG_RANK_0( "Well " << wellControls.getName() << " aft solve Constraint rates " << constraint->getName() << " bhp " << constraint->bottomHolePressure() << " phaseVolRate " << + constraint->phaseVolumeRates() << " totalVolRate " << constraint->totalVolumeRate() << " massRate " << constraint->massRate()); + } + } + + + } + +} + +bool CompositionalMultiphaseWell::evaluateProductionConstraints1( real64 const & time_n, + real64 const & dt, + integer const cycleNumber, + integer const coupledIterationNumber, + DomainPartition & domain, + MeshLevel & mesh, + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion, + DofManager const & dofManager ) +{ + WellControls & wellControls = getWellControls( subRegion ); + + + this->template solveConstraint< MinimumBHPConstraint >( time_n, + dt, + cycleNumber, + coupledIterationNumber, + domain, + mesh, + elemManager, + subRegion, + dofManager ); + + this->template solveConstraint< PhaseProductionConstraint, LiquidProductionConstraint, + MassProductionConstraint, TotalVolProductionConstraint >( time_n, + dt, + cycleNumber, + coupledIterationNumber, + domain, + mesh, + elemManager, + subRegion, + dofManager ); + + this->template selectLimitingConstraint< MinimumBHPConstraint, PhaseProductionConstraint, + MassProductionConstraint, TotalVolProductionConstraint >( time_n, + coupledIterationNumber, + subRegion ); + // this should be done in calculateLImitingConstraint + // wellControls.setControl( static_cast< WellControls::Control >(limitingConstraint->getControl()) ); // old + // wellControls.setCurrentConstraint( limitingConstraint ); // new + WellConstraintBase * limitingConstraint = wellControls.getCurrentConstraint(); + if( coupledIterationNumber < wellControls.estimateSolution() ) + { + + solveNonlinearSystem( time_n, + dt, + cycleNumber, + domain, + mesh, + elemManager, + subRegion, + dofManager ); + + } + limitingConstraint->setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); + limitingConstraint->setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( + CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); + limitingConstraint->setTotalVolumeRate ( wellControls.getReference< real64 >( + CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); + limitingConstraint->setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); + + GEOS_LOG_RANK_0( + " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << limitingConstraint->phaseVolumeRates() << " " << + limitingConstraint->totalVolumeRate() << " " << limitingConstraint->massRate()); + return true; +} + +bool +CompositionalMultiphaseWell:: + evaluateInjectionConstraints( real64 const & time_n, + real64 const & dt, + integer const cycleNumber, + integer const coupledIterationNumber, + DomainPartition & domain, + MeshLevel & mesh, + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion, + DofManager const & dofManager ) +{ + WellControls & wellControls = getWellControls( subRegion ); + + this->template solveConstraint< MaximumBHPConstraint >( time_n, + dt, + cycleNumber, + coupledIterationNumber, + domain, + mesh, + elemManager, + subRegion, + dofManager ); + + this->template solveConstraint< PhaseInjectionConstraint, + MassInjectionConstraint, TotalVolInjectionConstraint >( time_n, + dt, + cycleNumber, + coupledIterationNumber, + domain, + mesh, + elemManager, + subRegion, + dofManager ); + + this->template selectLimitingConstraint< MaximumBHPConstraint, PhaseInjectionConstraint, + MassInjectionConstraint, TotalVolInjectionConstraint >( time_n, + coupledIterationNumber, + subRegion ); + + // this should be done in calculateLimitingCosntraint + //wellControls.setControl( static_cast< WellControls::Control >(limitingConstraint->getControl()) ); // old + //wellControls.setCurrentConstraint( limitingConstraint ); // new + WellConstraintBase * limitingConstraint = wellControls.getCurrentConstraint(); + if( coupledIterationNumber < wellControls.estimateSolution() ) + { + + solveNonlinearSystem( time_n, + dt, + cycleNumber, + domain, + mesh, + elemManager, + subRegion, + dofManager ); + } + // Store computed well quantities for this constraint + limitingConstraint->setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); + limitingConstraint->setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( + CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); + limitingConstraint->setTotalVolumeRate ( wellControls.getReference< real64 >( + CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); + limitingConstraint->setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); + GEOS_LOG_RANK_0( + " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << limitingConstraint->phaseVolumeRates() << " " << + limitingConstraint->totalVolumeRate() << " " << limitingConstraint->massRate() ); + + return true; +} + +bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, + real64 const & dt, + integer const cycleNumber, + integer const coupledIterationNumber, + DomainPartition & domain, + MeshLevel & mesh, + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion, + DofManager const & dofManager ) +{ + WellControls & wellControls = getWellControls( subRegion ); + + bool useEstimator = coupledIterationNumber < wellControls.estimateSolution(); + + if( useEstimator ) + { + // create list of all constraints to solve + std::vector< std::shared_ptr< WellConstraintBase > > constraintList; + std::shared_ptr< WellConstraintBase > limitingConstraint = nullptr; + if( wellControls.isProducer() ) + { + constraintList = wellControls.getProdRateConstraints(); + // Solve minimum bhp constraint first + limitingConstraint = wellControls.getMinBHPConstraint(); + } + else + { + constraintList = wellControls.getInjRateConstraints(); + // Solve maximum bhp constraint first + limitingConstraint = wellControls.getMaxBHPConstraint(); + } + solveConstraint ( limitingConstraint, time_n, + dt, + cycleNumber, + coupledIterationNumber, + domain, + mesh, + elemManager, + subRegion, + dofManager ); + + for( auto const & constraint : constraintList ) + { + GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), + " Well " << subRegion.getName() << " Constraint " << constraint->getName() << " active " << constraint->isConstraintActive() << + " value " << constraint->getConstraintValue( time_n ) ); + if( constraint->isConstraintActive() && constraint->checkViolation( *limitingConstraint, time_n )) + { + limitingConstraint=constraint; + wellControls.setControl( static_cast< WellControls::Control >(constraint->getControl()) ); // tjb old + wellControls.setCurrentConstraint( limitingConstraint.get() ); + solveConstraint ( constraint, time_n, + dt, + cycleNumber, + coupledIterationNumber, + domain, + mesh, + elemManager, + subRegion, + dofManager ); + // tjb. this is likely not needed. set in update state + constraint->setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); + constraint->setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( + CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); + constraint->setTotalVolumeRate ( wellControls.getReference< real64 >( + CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); + constraint->setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); + + } + } + + GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), + " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << limitingConstraint->phaseVolumeRates() << " " << + limitingConstraint->totalVolumeRate() << " " << limitingConstraint->massRate()); + } + else + { + // create list of all constraints to process + std::vector< std::shared_ptr< WellConstraintBase > > constraintList; + if( wellControls.isProducer() ) + { + constraintList = wellControls.getProdRateConstraints(); + // Solve minimum bhp constraint first + constraintList.insert( constraintList.begin(), wellControls.getMinBHPConstraint() ); + } + else + { + constraintList = wellControls.getInjRateConstraints(); + // Solve maximum bhp constraint first; + constraintList.insert( constraintList.begin(), wellControls.getMaxBHPConstraint() ); + } + // Get current constraint + std::shared_ptr< WellConstraintBase > limitingConstraint = nullptr; + for( auto & constraint : constraintList ) + { + if( constraint->getName() == wellControls.getCurrentConstraint()->getName()) + { + limitingConstraint = constraint; + // tjb. this is likely not needed. set in update state + constraint->setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); + constraint->setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( + CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); + constraint->setTotalVolumeRate ( wellControls.getReference< real64 >( + CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); + constraint->setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); + GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), + " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << limitingConstraint->phaseVolumeRates() << " " << + limitingConstraint->totalVolumeRate() << " " << limitingConstraint->massRate()); + } + } + + + // Check current against other constraints + for( auto & constraint : constraintList ) + { + + if( limitingConstraint->getName() != constraint->getName()) + { + //std::cout << "Use estimator " << useEstimator << " Evaluating constraint " << constraint.getName() << " against constraint " << + // limitingConstraint->getName() << std::endl; + if( constraint->checkViolation( *limitingConstraint, time_n ) ) + { + wellControls.setControl( static_cast< WellControls::Control >(constraint->getControl()) ); // tjb old + wellControls.setCurrentConstraint( constraint.get() ); + GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), + " Well " << subRegion.getName() << " New Limiting Constraint " << constraint->getName() << " " << constraint->getConstraintValue( time_n ) ); + } + } + } + GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), + " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << limitingConstraint->phaseVolumeRates() << " " << + limitingConstraint->totalVolumeRate() << " " << limitingConstraint->massRate()); + } + return true; +} REGISTER_CATALOG_ENTRY( PhysicsSolverBase, CompositionalMultiphaseWell, string const &, Group * const ) } // namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp index fd874ec5a0e..2edcd74464b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp @@ -25,6 +25,8 @@ #include "physicsSolvers/fluidFlow/wells/WellSolverBase.hpp" #include "physicsSolvers/fluidFlow/CompositionalMultiphaseBase.hpp" +#include "physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp" + namespace geos { @@ -92,6 +94,13 @@ class CompositionalMultiphaseWell : public WellSolverBase /**@{*/ + virtual real64 + calculateWellResidualNorm( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs ) override; + virtual real64 calculateResidualNorm( real64 const & time_n, real64 const & dt, @@ -99,17 +108,37 @@ class CompositionalMultiphaseWell : public WellSolverBase DofManager const & dofManager, arrayView1d< real64 const > const & localRhs ) override; + virtual real64 + scalingForWellSystemSolution( ElementSubRegionBase & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution ) override; + virtual real64 scalingForSystemSolution( DomainPartition & domain, DofManager const & dofManager, arrayView1d< real64 const > const & localSolution ) override; + virtual bool + checkWellSystemSolution( ElementSubRegionBase & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor ) override; + virtual bool checkSystemSolution( DomainPartition & domain, DofManager const & dofManager, arrayView1d< real64 const > const & localSolution, real64 const scalingFactor ) override; + virtual void + applyWellSystemSolution( DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor, + real64 const dt, + DomainPartition & domain, + MeshLevel & mesh, + WellElementSubRegion & subRegion ) override; + virtual void applySystemSolution( DofManager const & dofManager, arrayView1d< real64 const > const & localSolution, @@ -159,6 +188,21 @@ class CompositionalMultiphaseWell : public WellSolverBase */ void updateFluidModel( WellElementSubRegion & subRegion ); + /** + * @brief Update well separator using current values of pressure and composition at the reference element + * @param subRegion the well subregion containing all the primary and dependent fields + * @param targetIndex the targetIndex of the subRegion + */ + void updateSeparator( WellElementSubRegion & subRegion ); + + /** + * @brief Calculate well rates at reference element + * @param subRegion the well subregion containing all the primary and dependent fields + * @param targetIndex the targetIndex of the subRegion + */ + + void calculateReferenceElementRates( WellElementSubRegion & subRegion ); + /** * @brief Recompute phase volume fractions (saturations) from constitutive and primary variables * @param subRegion the well subregion containing all the primary and dependent fields @@ -172,6 +216,16 @@ class CompositionalMultiphaseWell : public WellSolverBase */ void updateTotalMassDensity( WellElementSubRegion & subRegion ) const; + /** + * @brief Recompute the perforation rates for all the wells + * @param domain the domain containing the mesh and fields + */ + virtual void computeWellPerforationRates( real64 const & time_n, + real64 const & GEOS_UNUSED_PARAM( dt ), + ElementRegionManager const & elemManager, + WellElementSubRegion & subRegion )override; + + /** * @brief Recompute the perforation rates for all the wells * @param domain the domain containing the mesh and fields @@ -183,6 +237,7 @@ class CompositionalMultiphaseWell : public WellSolverBase * @brief Recompute all dependent quantities from primary variables (including constitutive models) * @param subRegion the well subregion containing all the primary and dependent fields */ + virtual real64 updateWellState( WellElementSubRegion & subRegion ) override; virtual void updateState( DomainPartition & domain ) override; virtual real64 updateSubRegionState( WellElementSubRegion & subRegion ) override; @@ -197,6 +252,13 @@ class CompositionalMultiphaseWell : public WellSolverBase integer useTotalMassEquation() const { return m_useTotalMassEquation; } + virtual void assembleWellFluxTerms( real64 const & time, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; + /** * @brief assembles the flux terms for all connections between well elements * @param time_n previous time value @@ -213,6 +275,14 @@ class CompositionalMultiphaseWell : public WellSolverBase DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs )override; + + virtual void assembleWellAccumulationTerms( real64 const & time, + real64 const & dt, + WellElementSubRegion & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; + /** * @brief assembles the accumulation term for all the well elements * @param domain the physical domain object @@ -227,6 +297,21 @@ class CompositionalMultiphaseWell : public WellSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) override; + virtual void assembleWellConstraintTerms( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; + + + virtual void assembleWellPressureRelations( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; + /** * @brief assembles the pressure relations at all connections between well elements except at the well head * @param time_n time at the beginning of the time step @@ -249,6 +334,8 @@ class CompositionalMultiphaseWell : public WellSolverBase */ void chopNegativeDensities( DomainPartition & domain ); + void chopNegativeDensities( WellElementSubRegion & subRegion ); + struct viewKeyStruct : WellSolverBase::viewKeyStruct { static constexpr char const * dofFieldString() { return "compositionalWellVars"; } @@ -312,6 +399,7 @@ class CompositionalMultiphaseWell : public WellSolverBase virtual void initializePostInitialConditionsPreSubGroups() override; + void saveState( WellElementSubRegion & subRegion ); virtual void postRestartInitialization() override final; /* * @brief Utility function that checks the consistency of the constitutive models @@ -357,6 +445,37 @@ class CompositionalMultiphaseWell : public WellSolverBase real64 const & dt, DomainPartition & domain ) override; + + bool evaluateProductionConstraints1( real64 const & time_n, + real64 const & stepDt, + integer const cycleNumber, + integer const coupledIterationNumber, + DomainPartition & domain, + MeshLevel & mesh, + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion, + DofManager const & dofManager ); + + virtual bool evaluateConstraints( real64 const & time_n, + real64 const & stepDt, + integer const cycleNumber, + integer const coupledIterationNumber, + DomainPartition & domain, + MeshLevel & mesh, + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion, + DofManager const & dofManager ) override; + + virtual bool evaluateInjectionConstraints( real64 const & time_n, + real64 const & stepDt, + integer const cycleNumber, + integer const coupledIterationNumber, + DomainPartition & domain, + MeshLevel & mesh, + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion, + DofManager const & dofManager )override; + private: /** @@ -365,8 +484,35 @@ class CompositionalMultiphaseWell : public WellSolverBase */ void initializeWells( DomainPartition & domain, real64 const & time_n ) override; + void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) override; + virtual void setConstitutiveNames( ElementSubRegionBase & subRegion ) const override; + template< typename ... GROUPTYPES > + void selectLimitingConstraint( real64 const & time_n, integer const coupledIterationNumber, WellElementSubRegion & subRegion ); + + void solveConstraint( std::shared_ptr< WellConstraintBase > constraint, + real64 const & time_n, + real64 const & dt, + integer const cycleNumber, + integer const coupledIterationNumber, + DomainPartition & domain, + MeshLevel & mesh, + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion, + DofManager const & dofManager ); + + template< typename GROUPTYPE, typename ... GROUPTYPES > + void solveConstraint( real64 const & time_n, + real64 const & stepDt, + integer const cycleNumber, + integer const coupledIterationNumber, + DomainPartition & domain, + MeshLevel & mesh, + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion, + DofManager const & dofManager ); + /// flag indicating whether mass or molar formulation should be used diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index 4d49a5062e4..4dd455afeb1 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -417,6 +417,13 @@ real64 SinglePhaseWell::updateSubRegionState( WellElementSubRegion & subRegion ) return 0.0; // change in phasevolume fraction doesnt apply } +void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) +{ + GEOS_UNUSED_VAR( domain ); + GEOS_UNUSED_VAR( mesh ); + GEOS_UNUSED_VAR( subRegion ); + GEOS_UNUSED_VAR( time_n ); +}; void SinglePhaseWell::initializeWells( DomainPartition & domain, real64 const & time_n ) { GEOS_MARK_FUNCTION; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp index 7bfeb996aa4..efd03cd276c 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp @@ -284,7 +284,7 @@ class SinglePhaseWell : public WellSolverBase * @param domain the domain containing the well manager to access individual wells */ void initializeWells( DomainPartition & domain, real64 const & time_n ) override; - + void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) override; /** * @brief Make sure that the well constraints are compatible * @param time_n the time at the beginning of the time step diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index 8c28ad66832..2b271873b58 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -205,13 +205,7 @@ Group * WellControls::createChild( string const & childKey, string const & child // CatalogInterface::unknownTypeError( childKey, getDataContext(), childTypes ) ); Group * constraint = nullptr; - if( childKey == viewKeyStruct::minimumWHPConstraintString() ) - { - MinimumWHPConstraint & whpConstraint = registerGroup< MinimumWHPConstraint >( childName ); - m_minWHPConstraint = std::shared_ptr< MinimumWHPConstraint >( &whpConstraint ); - constraint = &whpConstraint; - } - else if( childKey == viewKeyStruct::minimumBHPConstraintString() ) + if( childKey == viewKeyStruct::minimumBHPConstraintString() ) { MinimumBHPConstraint & bhpConstraint = registerGroup< MinimumBHPConstraint >( childName ); m_minBHPConstraint = std::shared_ptr< MinimumBHPConstraint >( &bhpConstraint ); @@ -269,32 +263,6 @@ Group * WellControls::createChild( string const & childKey, string const & child return constraint; } -void WellControls::createMinBHPConstraintForWHP() -{ - // Create constraint and set local pointer - MinimumBHPConstraint & bhpConstraint = registerGroup< MinimumBHPConstraint >( m_minWHPConstraint->getName()+"MinimumBHPConstraint" ); - m_minBHPConstraintForWHP = std::shared_ptr< MinimumBHPConstraint >( &bhpConstraint ); - // Set properties from the original minBHP constraint - m_minBHPConstraintForWHP->setReferenceElevation( m_minBHPConstraint->getReferenceElevation() ); - m_minBHPConstraintForWHP->setReferenceGravityCoef ( m_minBHPConstraint->getReferenceGravityCoef() ); - // Set to inactive. WHP estimator solve will set status - m_minBHPConstraintForWHP->setConstraintActive( false ); -} -void WellControls::createMaxLiquidConstraintForWHP() -{ - // Create constraint and set local pointer - LiquidProductionConstraint & liquidConstraint = registerGroup< LiquidProductionConstraint >( m_minWHPConstraint->getName()+"LiquidProductionConstraint" ); - m_maxLiquidConstraintForWHP = std::shared_ptr< LiquidProductionConstraint >( &liquidConstraint ); - // Set properties from VFP table - FunctionManager & functionManager = FunctionManager::getInstance(); - const PipeFlowTableFunction & m_flowTable = functionManager.getGroup< PipeFlowTableFunction const >( m_minWHPConstraint->getFlowTableName()); - string_array ratePhases = m_flowTable.getRatePhases(); - m_maxLiquidConstraintForWHP->setPhaseNames( ratePhases ); - m_maxLiquidConstraintForWHP->validateLiquidType( getMultiFluidSeparator()); - // WHP estimator solve will set status - m_maxLiquidConstraintForWHP->setConstraintActive( false ); -} - void WellControls::expandObjectCatalogs() { //createChild( keys::wellControls, keys::wellControls ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp index 67216530306..c6553479894 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp @@ -445,7 +445,7 @@ class WellControls : public dataRepository::Group /// string key for the esitmate well solution flag static constexpr char const * estimateWellSolutionString() { return "estimateWellSolution"; } - /// string key for the minimum BHP presssure for a producer + /// string key for the minimum BHP presssure for a producer static constexpr char const * minimumBHPConstraintString() { return "MinimumBHPConstraint"; } /// string key for the maximum BHP presssure for a injection static constexpr char const * maximumBHPConstraintString() { return "MaximumBHPConstraint"; } @@ -483,8 +483,6 @@ class WellControls : public dataRepository::Group std::shared_ptr< MinimumBHPConstraint > getMinBHPConstraint() { return m_minBHPConstraint; }; std::shared_ptr< MaximumBHPConstraint > getMaxBHPConstraint() { return m_maxBHPConstraint; }; - std::shared_ptr< LiquidProductionConstraint > getMaxLiquidConstraintForWHP() { return m_maxLiquidConstraintForWHP; }; - std::shared_ptr< MinimumBHPConstraint > getMinimumBHPConstraintForWHP() { return m_minBHPConstraintForWHP; }; // Lists of rate constraints std::vector< std::shared_ptr< WellConstraintBase > > getProdRateConstraints() { return m_productionRateConstraintList; }; std::vector< std::shared_ptr< WellConstraintBase > > getInjRateConstraints() { return m_injectionRateConstraintList; } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp index e470984d7cd..780128bc4b2 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp @@ -43,7 +43,9 @@ WellSolverBase::WellSolverBase( string const & name, m_numDofPerResElement( 0 ), m_isThermal( 0 ), m_ratesOutputDir( joinPath( OutputBase::getOutputDirectory(), name + "_rates" ) ), - m_keepVariablesConstantDuringInitStep( false ) + m_keepVariablesConstantDuringInitStep( false ), + + m_useNewCode( true ) { registerWrapper( viewKeyStruct::isThermalString(), &m_isThermal ). setApplyDefaultValue( 0 ). @@ -63,6 +65,12 @@ WellSolverBase::WellSolverBase( string const & name, setInputFlag( dataRepository::InputFlags::OPTIONAL ). setDescription( "Choose time step to honor rates/bhp tables time intervals" ); + this->registerWrapper( viewKeyStruct::useNewCodeString(), &m_useNewCode ). + setApplyDefaultValue( 1 ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Use new code" ); + + addLogLevel< logInfo::WellControl >(); } @@ -293,10 +301,218 @@ void WellSolverBase::implicitStepSetup( real64 const & time_n, setPerforationStatus( time_n, domain ); // Initialize the primary and secondary variables for the first time step + if( !m_useNewCode ) + { + initializeWells( domain, time_n ); + } - initializeWells( domain, time_n ); } +void WellSolverBase::setupWellDofs( DomainPartition & domain ) +{ + if( m_estimatorDoFManager.empty() ) + { + + map< std::pair< string, string >, string_array > meshTargets; + string_array regions; + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + meshTargets.clear(); + regions.clear(); + regions.emplace_back( region.getName() ); + auto const key = std::make_pair( meshBodyName, meshLevel.getName()); + meshTargets[key] = std::move( regions ); + + DofManager regionDoFManager( region.getName()); + regionDoFManager.setDomain( domain ); + regionDoFManager.addField( wellElementDofName(), + FieldLocation::Elem, + numDofPerWellElement(), + meshTargets ); + + regionDoFManager.addCoupling( wellElementDofName(), + wellElementDofName(), + DofManager::Connector::Node ); + + regionDoFManager.reorderByRank(); + m_estimatorDoFManager.emplace( region.getName(), std::move( regionDoFManager )); + } ); + } ); + } +} + +void WellSolverBase::selectWellConstraint( real64 const & time_n, + real64 const & dt, + const integer cycleNumber, + const integer coupledIterationNumber, + DomainPartition & domain ) +{ + GEOS_MARK_FUNCTION; + + //GEOS_LOG_RANK( "**** Estimate Well Solution - Start **** " << getName() ); + setupWellDofs( domain ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = getWellControls( subRegion ); + if( wellControls.isWellOpen() ) + { + if( !wellControls.getWellState() ) + { + wellControls.setWellState( 1 ); + + initializeWell( domain, meshLevel, subRegion, time_n ); + } + } + else + { + wellControls.setWellState( 0 ); + } + + + if( wellControls.getWellState()) + { + //GEOS_LOG_RANK( "**** Estimate Well Solution - Start **** " << subRegion.getName() ); + auto it = m_estimatorDoFManager.find( region.getName()); + if( it == m_estimatorDoFManager.end()) + { + throw std::runtime_error( "DofManager for region " + region.getName() + " not found." ); + } + DofManager & dofManager = it->second; + +// Only build the sparsity pattern if the mesh has changed + Timestamp const meshModificationTimestamp = getMeshModificationTimestamp( domain ); + + if( meshModificationTimestamp > getSystemSetupTimestamp() ) + { + // These are esitmator matrices + setupWellSystem( domain, dofManager, m_localMatrix, m_rhs, m_solution ); + //setSystemSetupTimestamp( meshModificationTimestamp ); + + //std::ostringstream oss; + //m_dofManager.printFieldInfo( oss ); + //GEOS_LOG_LEVEL( logInfo::Fields, oss.str()) + } + + + wellControls.setConstraintSwitch( false ); +#if 1 + evaluateConstraints( time_n, + dt, + cycleNumber, + coupledIterationNumber, + domain, + meshLevel, + elementRegionManager, + subRegion, + dofManager ); +#else + if( wellControls.isProducer()) + { + evaluateProductionConstraints( time_n, + dt, + cycleNumber, + coupledIterationNumber, + domain, + meshLevel, + elementRegionManager, + subRegion, + dofManager ); + } + else + { + evaluateInjectionConstraints( time_n, + dt, + cycleNumber, + coupledIterationNumber, + domain, + meshLevel, + elementRegionManager, + subRegion, + dofManager ); + } +#endif + // If a well is opened and then timestep is cut resulting in the well being shut, if the well is opened + // the well initialization code requires control type to by synced + integer owner = -1; + // Only subregion owner evaluates well control and control changes need to be broadcast to all ranks + if( subRegion.isLocallyOwned() ) + { + owner = MpiWrapper::commRank( MPI_COMM_GEOS ); + } + owner = MpiWrapper::max( owner ); + WellControls::Control wellControl = wellControls.getControl(); + MpiWrapper::broadcast( wellControl, owner ); + wellControls.setControl( wellControl ); + + //implicitStepSetup( time_n, dt, domain ); + +// currently the only method is implicit time integration + //real64 const dt_return = nonlinearImplicitStep( time_n, dt, cycleNumber, domain ); + +// final step for completion of timestep. typically secondary variable updates and cleanup. + //implicitStepComplete( time_n, dt_return, domain ); + /* + solveNonlinearSystem( time_n, + dt, + cycleNumber, + domain, + meshLevel, + elementRegionManager, + subRegion, + dofManager ); + */ + + //GEOS_LOG_RANK( "**** Estimate Well Solution End **** " << subRegion.getName()); + } + + } ); + } ); + //GEOS_LOG_RANK( "**** Estimate Well Solution End **** " << getName()); +} + +void WellSolverBase::setupWellSystem( DomainPartition & domain, + DofManager & dofManager, + CRSMatrix< real64, globalIndex > & localMatrix, + ParallelVector & rhs, + ParallelVector & solution, + bool const setSparsity ) +{ + GEOS_MARK_FUNCTION; + + setupWellDofs( domain ); + + if( setSparsity ) + { + SparsityPattern< globalIndex > pattern; + dofManager.setSparsityPattern( pattern ); + localMatrix.assimilate< parallelDevicePolicy<> >( std::move( pattern ) ); + } + localMatrix.setName( this->getName() + "/matrix" ); + + rhs.setName( this->getName() + "/rhs" ); + rhs.create( dofManager.numLocalDofs(), MPI_COMM_GEOS ); + + solution.setName( this->getName() + "/solution" ); + solution.create( dofManager.numLocalDofs(), MPI_COMM_GEOS ); +} void WellSolverBase::updateState( DomainPartition & domain ) { GEOS_MARK_FUNCTION; @@ -311,6 +527,27 @@ void WellSolverBase::updateState( DomainPartition & domain ) } ); } +void WellSolverBase::assembleWellSystem( real64 const time_n, + real64 const dt, + ElementRegionManager const & elementRegionManager, + WellElementSubRegion & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + assembleWellAccumulationTerms( time_n, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); + WellControls & wellControls = getWellControls( subRegion ); + if( !wellControls.getConstraintSwitch() ) + { + + assembleWellConstraintTerms( time_n, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); + } + assembleWellPressureRelations( time_n, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); + computeWellPerforationRates( time_n, dt, elementRegionManager, subRegion ); + assembleWellFluxTerms( time_n, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); + +} + void WellSolverBase::assembleSystem( real64 const time, real64 const dt, DomainPartition & domain, @@ -318,13 +555,43 @@ void WellSolverBase::assembleSystem( real64 const time, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - string const wellDofKey = dofManager.getKey( wellElementDofName()); + + if( m_useNewCode ) + { + // selects constraints one of 2 ways + // wellEstimator flag set to 0 => orginal logic rates are computed during update state and constraints are selected every newton + // iteration + // wellEstimator flag > 0 => well esitmator solved for each constraint and then selects the constraint + // => estimator solve only performed first "wellEstimator" iterations + + selectWellConstraint( time, dt, 0, geos::currentCoupledNewton, domain ); + } + // assemble the accumulation term in the mass balance equations assembleAccumulationTerms( time, dt, domain, dofManager, localMatrix, localRhs ); // then assemble the pressure relations between well elements assemblePressureRelations( time, dt, domain, dofManager, localMatrix, localRhs ); + //if( false && m_useNewCode ) + { + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + ElementRegionManager & elementRegionManager = mesh.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = getWellControls( subRegion ); + if( !wellControls.getConstraintSwitch() ) + assembleWellConstraintTerms( time, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); + } ); + } ); + } // then compute the perforation rates (later assembled by the coupled solver) computePerforationRates( time, dt, domain ); @@ -386,8 +653,15 @@ void WellSolverBase::precomputeData( DomainPartition & domain ) wellElemGravCoef[iwelem] = LvArray::tensorOps::AiBi< 3 >( wellElemLocation[iwelem], gravVector ); } ); + wellControls.forSubGroups< BHPConstraint >( [&]( auto & constraint ) + { + // set the reference well element where the BHP control is applied + real64 const refElev1 = constraint.getReferenceElevation(); + constraint.setReferenceGravityCoef( refElev1 * gravVector[2] ); + } ); + // set the reference well element where the BHP control is applied - wellControls.setReferenceGravityCoef( refElev * gravVector[2] ); + wellControls.setReferenceGravityCoef( refElev * gravVector[2] ); // tjb remove } ); } ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp index a8159378b50..557d360f312 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp @@ -189,6 +189,15 @@ class WellSolverBase : public PhysicsSolverBase * @param matrix the system matrix * @param rhs the system right-hand side vector */ + + void assembleWellSystem( real64 const time, + real64 const dt, + ElementRegionManager const & elementRegionManager, + WellElementSubRegion & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ); + virtual void assembleSystem( real64 const time, real64 const dt, DomainPartition & domain, @@ -196,6 +205,14 @@ class WellSolverBase : public PhysicsSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) override; + virtual void assembleWellFluxTerms( real64 const & GEOS_UNUSED_PARAM( time ), + real64 const & GEOS_UNUSED_PARAM( dt ), + WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ), + CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), + arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) {}; + + /** * @brief assembles the flux terms for all connections between well elements * @param time_n previous time value @@ -212,6 +229,16 @@ class WellSolverBase : public PhysicsSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) = 0; + + + virtual void assembleWellAccumulationTerms( real64 const & GEOS_UNUSED_PARAM( time ), + real64 const & GEOS_UNUSED_PARAM( dt ), + WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ), + CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), + arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) {}; + + /** * @brief assembles the accumulation term for all the well elements * @param domain the physical domain object @@ -226,6 +253,19 @@ class WellSolverBase : public PhysicsSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) = 0; + virtual void assembleWellConstraintTerms( real64 const & GEOS_UNUSED_PARAM( time ), + real64 const & GEOS_UNUSED_PARAM( dt ), + WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ), + CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), + arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) {}; + + virtual void assembleWellPressureRelations( real64 const & GEOS_UNUSED_PARAM( time ), + real64 const & GEOS_UNUSED_PARAM( dt ), + WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ), + CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), + arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) {}; /** * @brief assembles the pressure relations at all connections between well elements except at the well head * @param time_n time at the beginning of the time step @@ -246,6 +286,7 @@ class WellSolverBase : public PhysicsSolverBase * @brief Recompute all dependent quantities from primary variables (including constitutive models) * @param domain the domain containing the mesh and fields */ + virtual real64 updateWellState( WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ) ){return 0.0;}; virtual void updateState( DomainPartition & domain ) override; /** @@ -254,6 +295,12 @@ class WellSolverBase : public PhysicsSolverBase */ virtual real64 updateSubRegionState( WellElementSubRegion & subRegion ) = 0; + + virtual void computeWellPerforationRates( real64 const & GEOS_UNUSED_PARAM( time_n ), + real64 const & GEOS_UNUSED_PARAM( dt ), + ElementRegionManager const & GEOS_UNUSED_PARAM( elemManager ), + WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ) ){} + /** * @brief Recompute the perforation rates for all the wells * @param domain the domain containing the mesh and fields @@ -262,6 +309,73 @@ class WellSolverBase : public PhysicsSolverBase real64 const & dt, DomainPartition & domain ) = 0; + virtual real64 + calculateWellResidualNorm( real64 const & GEOS_UNUSED_PARAM( time_n ), + real64 const & GEOS_UNUSED_PARAM( dt ), + WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ), + arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localRhs ) ) {return std::numeric_limits< real64 >::max();}; + bool solveNonlinearSystem( real64 const & time_n, + real64 const & stepDt, + integer const cycleNumber, + DomainPartition & domain, + MeshLevel & mesh, + ElementRegionManager & elementRegionManager, + WellElementSubRegion & subregion, + DofManager const & dofManager ); + + virtual real64 + scalingForWellSystemSolution( ElementSubRegionBase & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ), + arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localSolution ) ) {return std::numeric_limits< real64 >::max();}; + + virtual bool + checkWellSystemSolution( ElementSubRegionBase & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ), + arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localSolution ), + real64 const GEOS_UNUSED_PARAM( scalingFactor ) ) {return false;}; + virtual void + applyWellSystemSolution( DofManager const & GEOS_UNUSED_PARAM( dofManager ), + arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localSolution ), + real64 const GEOS_UNUSED_PARAM( scalingFactor ), + real64 const GEOS_UNUSED_PARAM( dt ), + DomainPartition & GEOS_UNUSED_PARAM( domain ), + MeshLevel & GEOS_UNUSED_PARAM( mesh ), + WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ) ) {}; + + /** + * @brief Function to perform line search + * @param time_n time at the beginning of the step + * @param dt the perscribed timestep + * @param cycleNumber the current cycle number + * @param domain the domain object + * @param dofManager degree-of-freedom manager associated with the linear system + * @param localMatrix the system matrix + * @param rhs the system right-hand side vector + * @param solution the solution vector + * @param scaleFactor the scaling factor to apply to the solution + * @param lastResidual (in) target value below which to reduce residual norm, (out) achieved residual norm + * @return return true if line search succeeded, false otherwise + * + * This function implements a nonlinear newton method for implicit problems. It requires that the + * other functions in the solver interface are implemented in the derived physics solver. The + * nonlinear loop includes a simple line search algorithm, and will cut the timestep if + * convergence is not achieved according to the parameters in linearSolverParameters member. + */ + bool + lineSearch1( real64 const & time_n, + real64 const & dt, + integer const cycleNumber, + DomainPartition & domain, + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion, + MeshLevel & mesh, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + ParallelVector & rhs, + ParallelVector & solution, + real64 const scaleFactor, + real64 & lastResidual ); /** * @brief function to set the next time step size * @param[in] currentTime the current time @@ -286,6 +400,7 @@ class WellSolverBase : public PhysicsSolverBase static constexpr char const * isThermalString() { return "isThermal"; } static constexpr char const * writeCSVFlagString() { return "writeCSV"; } static constexpr char const * timeStepFromTablesFlagString() { return "timeStepFromTables"; } + static constexpr char const * useNewCodeString() { return "useNewCode"; } static constexpr char const * fluidNamesString() { return "fluidNames"; } }; @@ -311,7 +426,7 @@ class WellSolverBase : public PhysicsSolverBase * @param domain the domain containing the well manager to access individual wells */ virtual void initializeWells( DomainPartition & domain, real64 const & time_n ) = 0; - + virtual void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) = 0; /** * @brief Make sure that the well constraints are compatible * @param time_n the time at the beginning of the time step @@ -327,6 +442,35 @@ class WellSolverBase : public PhysicsSolverBase real64 const & dt, DomainPartition & domain ) = 0; + virtual bool evaluateConstraints( real64 const & GEOS_UNUSED_PARAM( time_n ), + real64 const & GEOS_UNUSED_PARAM( stepDt ), + integer const GEOS_UNUSED_PARAM( cycleNumber ), + integer const GEOS_UNUSED_PARAM( coupledIterationNumber ), + DomainPartition & GEOS_UNUSED_PARAM( domain ), + MeshLevel & GEOS_UNUSED_PARAM( mesh ), + ElementRegionManager & GEOS_UNUSED_PARAM( elemManager ), + WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ) ) { return false;}; + + virtual bool evaluateProductionConstraints( real64 const & GEOS_UNUSED_PARAM( time_n ), + real64 const & GEOS_UNUSED_PARAM( stepDt ), + integer const GEOS_UNUSED_PARAM( cycleNumber ), + integer const GEOS_UNUSED_PARAM( coupledIterationNumber ), + DomainPartition & GEOS_UNUSED_PARAM( domain ), + MeshLevel & GEOS_UNUSED_PARAM( mesh ), + ElementRegionManager & GEOS_UNUSED_PARAM( elemManager ), + WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ) ) { return false;}; + + virtual bool evaluateInjectionConstraints( real64 const & GEOS_UNUSED_PARAM( time_n ), + real64 const & GEOS_UNUSED_PARAM( stepDt ), + integer const GEOS_UNUSED_PARAM( cycleNumber ), + integer const GEOS_UNUSED_PARAM( coupledIterationNumber ), + DomainPartition & GEOS_UNUSED_PARAM( domain ), + MeshLevel & GEOS_UNUSED_PARAM( mesh ), + ElementRegionManager & GEOS_UNUSED_PARAM( elemManager ), + WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ) ) {return true;}; /// name of the flow solver string m_flowSolverName; @@ -357,6 +501,13 @@ class WellSolverBase : public PhysicsSolverBase /// name of the fluid constitutive model used as a reference for component/phase description string m_referenceFluidModelName; + + /// flag to use the estimator + integer m_estimateSolution; + + + integer m_useNewCode; + }; } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp index aff9a909137..0335333c898 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp @@ -38,18 +38,18 @@ inline void ControlEquationHelper:: selectLimitingConstraint( bool const isProducer, - WellControls::Control const & inputControl, - WellControls::Control const & currentControl, - integer const phasePhaseIndex, - real64 const & targetBHP, - real64 const & targetPhaseRate, - real64 const & targetTotalRate, - real64 const & targetMassRate, - real64 const & currentBHP, - arrayView1d< real64 const > const & currentPhaseVolRate, - real64 const & currentTotalVolRate, - real64 const & currentMassRate, - WellControls::Control & newControl ) + WellControls::Control const & inputControl, + WellControls::Control const & currentControl, + integer const phasePhaseIndex, + real64 const & targetBHP, + real64 const & targetPhaseRate, + real64 const & targetTotalRate, + real64 const & targetMassRate, + 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 bool controlIsViable = false; @@ -376,18 +376,18 @@ PressureRelationKernel:: { ControlEquationHelper::selectLimitingConstraint( isProducer, - inputControl, - currentControl, - targetPhaseIndex, - targetBHP, - targetPhaseRate, - targetTotalRate, - targetMassRate, - currentBHP, - currentPhaseVolRate, - currentTotalVolRate, - currentMassRate, - newControl ); + inputControl, + currentControl, + targetPhaseIndex, + targetBHP, + targetPhaseRate, + targetTotalRate, + targetMassRate, + currentBHP, + currentPhaseVolRate, + currentTotalVolRate, + currentMassRate, + newControl ); } else { @@ -400,24 +400,24 @@ PressureRelationKernel:: } if( constraintSwitch ) { - ControlEquationHelper::compute< NC, IS_THERMAL >( rankOffset, - newControl, + ControlEquationHelper::compute< NC, IS_THERMAL >( rankOffset, + newControl, targetPhaseIndex, // tjb - remove ? targetBHP, // tjb - remove targetPhaseRate, // tjb - remove targetTotalRate, // tjb - remove targetMassRate, // tjb - remove targetValue, // tjb - currentBHP, - dCurrentBHP, - currentPhaseVolRate, - dCurrentPhaseVolRate, - currentTotalVolRate, - dCurrentTotalVolRate, - massDensity, - wellElemDofNumber[iwelemControl], - localMatrix, - localRhs ); + currentBHP, + dCurrentBHP, + currentPhaseVolRate, + dCurrentPhaseVolRate, + currentTotalVolRate, + dCurrentTotalVolRate, + massDensity, + wellElemDofNumber[iwelemControl], + localMatrix, + localRhs ); } // TODO: for consistency, we should assemble here, not in compute... diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp index 6e28ff049e9..32826be15e3 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp @@ -135,18 +135,18 @@ struct ControlEquationHelper static void selectLimitingConstraint( bool const isProducer, - WellControls::Control const & inputControl, - WellControls::Control const & currentControl, - integer const phasePhaseIndex, - real64 const & targetBHP, - real64 const & targetPhaseRate, - real64 const & targetTotalRate, - real64 const & targetMassRate, - real64 const & currentBHP, - arrayView1d< real64 const > const & currentPhaseVolRate, - real64 const & currentTotalVolRate, - real64 const & currentMassRate, - WellControls::Control & newControl ); + WellControls::Control const & inputControl, + WellControls::Control const & currentControl, + integer const phasePhaseIndex, + real64 const & targetBHP, + real64 const & targetPhaseRate, + real64 const & targetTotalRate, + real64 const & targetMassRate, + real64 const & currentBHP, + arrayView1d< real64 const > const & currentPhaseVolRate, + real64 const & currentTotalVolRate, + real64 const & currentMassRate, + WellControls::Control & newControl ); template< integer NC, integer IS_THERMAL > GEOS_HOST_DEVICE @@ -160,6 +160,7 @@ struct ControlEquationHelper real64 const & targetTotalRate, real64 const & targetMassRate, real64 const & currentBHP, + real64 const & targetValue, arrayView1d< real64 const > const & dCurrentBHP, arrayView1d< real64 const > const & currentPhaseVolRate, arrayView2d< real64 const > const & dCurrentPhaseVolRate, From c59b1a6f8675603dc6eed75cc0129798978711a9 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 30 Sep 2025 07:19:14 -0700 Subject: [PATCH 03/71] fix integrate errors --- .../wells/CompositionalMultiphaseWell.cpp | 571 ++++-------------- .../wells/CompositionalMultiphaseWell.hpp | 36 +- .../fluidFlow/wells/WellSolverBase.cpp | 171 +----- .../fluidFlow/wells/WellSolverBase.hpp | 58 +- .../wells/kernels/PerforationFluxKernels.hpp | 4 +- 5 files changed, 148 insertions(+), 692 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 50d9ead0bb7..c4aa752a4bb 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -2344,6 +2344,96 @@ CompositionalMultiphaseWell::checkSystemSolution( DomainPartition & domain, return globalCheck; } +void CompositionalMultiphaseWell::computeWellPerforationRates( real64 const & time_n, + real64 const & GEOS_UNUSED_PARAM( dt ), + ElementRegionManager const & elemManager, + WellElementSubRegion & subRegion ) +{ + GEOS_MARK_FUNCTION; + GEOS_UNUSED_VAR( time_n ); + + CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); + + PerforationData * const perforationData = subRegion.getPerforationData(); + WellControls const & wellControls = getWellControls( subRegion ); + if( wellControls.isWellOpen() && !m_keepVariablesConstantDuringInitStep ) + { + + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + bool isThermal = fluid.isThermal(); + + if( isThermal ) + { + thermalPerforationFluxKernels:: + PerforationFluxKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_numComponents, + m_numPhases, + flowSolver.getName(), + perforationData, + subRegion, + fluid, + elemManager, + wellControls.isInjector(), + wellControls.isCrossflowEnabled()); + } + else + { + isothermalPerforationFluxKernels:: + PerforationFluxKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_numComponents, + m_numPhases, + flowSolver.getName(), + perforationData, + subRegion, + elemManager, + wellControls.isInjector(), + wellControls.isCrossflowEnabled() ); + } + } + else + { +// Zero completion flow rate + arrayView2d< real64 > const compPerfRate = perforationData->getField< fields::well::compPerforationRate >(); + for( integer iperf=0; iperfsize(); iperf++ ) + { + for( integer ic = 0; ic < m_numComponents; ++ic ) + { + compPerfRate[iperf][ic] = 0.0; + } + } + } + + +} + + +void CompositionalMultiphaseWell::computePerforationRates( real64 const & time_n, + real64 const & dt, + DomainPartition & domain ) +{ + GEOS_MARK_FUNCTION; + GEOS_UNUSED_VAR( dt ); + forDiscretizationOnMeshTargets ( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + + // TODO: change the way we access the flowSolver here + + ElementRegionManager & elemManager = mesh.getElemManager(); + + elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + computeWellPerforationRates( time_n, dt, elemManager, subRegion ); + + } ); + + } ); + +} + void CompositionalMultiphaseWell::applyWellSystemSolution( DofManager const & dofManager, arrayView1d< real64 const > const & localSolution, @@ -3105,475 +3195,72 @@ void CompositionalMultiphaseWell::printRates( real64 const & time_n, } -template< typename ... GROUPTYPES > -void CompositionalMultiphaseWell::selectLimitingConstraint( real64 const & time_n, - - integer const coupledIterationNumber, - - WellElementSubRegion & subRegion ) +bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, + real64 const & dt, + integer const cycleNumber, + integer const coupledIterationNumber, + DomainPartition & domain, + MeshLevel & mesh, + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion ) { - WellControls & wellControls = getWellControls( subRegion ); - - bool useEstimator = coupledIterationNumber < wellControls.estimateSolution(); - if( useEstimator ) + // create list of all constraints to process + std::vector< std::shared_ptr< WellConstraintBase > > constraintList; + if( wellControls.isProducer() ) { - - // find limiting constraint - WellConstraintBase * limitingConstraint = nullptr; - wellControls.forSubGroups< WellConstraintBase, GROUPTYPES... >( [&]( auto & constraint ) - { - //std::cout << "Use estimator " << useEstimator << " valuating constraint " << constraint.getName() << std::endl; - if( limitingConstraint != nullptr && constraint.isConstraintActive() ) - std::cout << " against constraint " << limitingConstraint->getName() << std::endl; - if( constraint.isConstraintActive() ) - { - if( limitingConstraint == nullptr || constraint.checkViolation( *limitingConstraint, time_n )) - { - limitingConstraint = &constraint; - - std::cout << "New limiting constraint " << constraint.getName() << std::endl; - - wellControls.setControl( static_cast< WellControls::Control >(limitingConstraint->getControl()) ); // tjb old - wellControls.setCurrentConstraint( limitingConstraint ); - } - } - } ); - + constraintList = wellControls.getProdRateConstraints(); + // Solve minimum bhp constraint first + constraintList.insert( constraintList.begin(), wellControls.getMinBHPConstraint() ); } else { - // Get current constraint - WellConstraintBase * limitingConstraint = nullptr; - wellControls.forSubGroups< WellConstraintBase, GROUPTYPES... >( [&]( auto & constraint ) - { - if( constraint.getName() == wellControls.getCurrentConstraint()->getName()) - { - limitingConstraint = &constraint; - // tjb. this is likely not needed. set in update state - constraint.setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); - constraint.setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( - CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); - constraint.setTotalVolumeRate ( wellControls.getReference< real64 >( - CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); - constraint.setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); - wellControls.setControl( static_cast< WellControls::Control >(limitingConstraint->getControl()) ); // tjb old - wellControls.setCurrentConstraint( limitingConstraint ); - } - } ); - - - + constraintList = wellControls.getInjRateConstraints(); + // Solve maximum bhp constraint first; + constraintList.insert( constraintList.begin(), wellControls.getMaxBHPConstraint() ); } -} - - -template< typename GROUPTYPE, typename ... GROUPTYPES > -void CompositionalMultiphaseWell::solveConstraint( real64 const & time_n, - real64 const & dt, - integer const cycleNumber, - integer const coupledIterationNumber, - DomainPartition & domain, - MeshLevel & mesh, - ElementRegionManager & elemManager, - WellElementSubRegion & subRegion, - DofManager const & dofManager ) -{ - - WellControls & wellControls = getWellControls( subRegion ); - bool useEstimator = coupledIterationNumber < wellControls.estimateSolution(); - if( useEstimator ) + // Get current constraint + std::shared_ptr< WellConstraintBase > limitingConstraint = nullptr; + for( auto & constraint : constraintList ) { - - wellControls.forSubGroups< GROUPTYPE, GROUPTYPES... >( [&]( auto & constraint ) + if( constraint->getName() == wellControls.getCurrentConstraint()->getName()) { - if( getLogLevel() > 4 ) - { - GEOS_LOG_RANK_0( "Well " << wellControls.getName() << " Evaluating constraint " << constraint.getName() << " value " << constraint.getConstraintValue( time_n ) << " active " << - constraint.isConstraintActive() ); - } - if( constraint.isConstraintActive() ) - { - wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old - wellControls.setCurrentConstraint( &constraint ); - // If a well is opened and then timestep is cut resulting in the well being shut, if the well is opened -// the well initialization code requires control type to by synced - integer owner = -1; -// Only subregion owner evaluates well control and control changes need to be broadcast to all ranks - if( subRegion.isLocallyOwned() ) - { - owner = MpiWrapper::commRank( MPI_COMM_GEOS ); - } - owner = MpiWrapper::max( owner ); - WellControls::Control wellControl = wellControls.getControl(); - MpiWrapper::broadcast( wellControl, owner ); - wellControls.setControl( wellControl ); - solveNonlinearSystem( time_n, - dt, - cycleNumber, - domain, - mesh, - elemManager, - subRegion, - dofManager ); - - // Store computed well quantities for this constraint - constraint.setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); - constraint.setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( - CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); - constraint.setTotalVolumeRate ( wellControls.getReference< real64 >( - CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); - constraint.setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); - if( getLogLevel() > 4 ) - { - GEOS_LOG_RANK_0( "Well " << wellControls.getName() << " aft solve Constraint rates " << constraint.getName() << " bhp " << constraint.bottomHolePressure() << " phaseVolRate " << - constraint.phaseVolumeRates() << " totalVolRate " << constraint.totalVolumeRate() << " massRate " << constraint.massRate()); - } - } - } ); - - } - -} - - -void CompositionalMultiphaseWell::solveConstraint( std::shared_ptr< WellConstraintBase > constraint, - real64 const & time_n, - real64 const & dt, - integer const cycleNumber, - integer const coupledIterationNumber, - DomainPartition & domain, - MeshLevel & mesh, - ElementRegionManager & elemManager, - WellElementSubRegion & subRegion, - DofManager const & dofManager ) -{ - - WellControls & wellControls = getWellControls( subRegion ); - bool useEstimator = coupledIterationNumber < wellControls.estimateSolution(); - if( useEstimator ) - { - - if( getLogLevel() > 4 ) - { - GEOS_LOG_RANK_0( "Well " << wellControls.getName() << " Evaluating constraint " << constraint->getName() << " value " << constraint->getConstraintValue( time_n ) << " active " << - constraint->isConstraintActive() ); - } - if( constraint->isConstraintActive() ) - { - wellControls.setControl( static_cast< WellControls::Control >(constraint->getControl()) ); // tjb old - wellControls.setCurrentConstraint( constraint.get() ); - // If a well is opened and then timestep is cut resulting in the well being shut, if the well is opened -// the well initialization code requires control type to by synced - integer owner = -1; -// Only subregion owner evaluates well control and control changes need to be broadcast to all ranks - if( subRegion.isLocallyOwned() ) - { - owner = MpiWrapper::commRank( MPI_COMM_GEOS ); - } - owner = MpiWrapper::max( owner ); - WellControls::Control wellControl = wellControls.getControl(); - MpiWrapper::broadcast( wellControl, owner ); - wellControls.setControl( wellControl ); - solveNonlinearSystem( time_n, - dt, - cycleNumber, - domain, - mesh, - elemManager, - subRegion, - dofManager ); - - // Store computed well quantities for this constraint + limitingConstraint = constraint; + // tjb. this is likely not needed. set in update state constraint->setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); constraint->setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); constraint->setTotalVolumeRate ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); constraint->setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); - if( getLogLevel() > 4 ) - { - GEOS_LOG_RANK_0( "Well " << wellControls.getName() << " aft solve Constraint rates " << constraint->getName() << " bhp " << constraint->bottomHolePressure() << " phaseVolRate " << - constraint->phaseVolumeRates() << " totalVolRate " << constraint->totalVolumeRate() << " massRate " << constraint->massRate()); - } + GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), + " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << limitingConstraint->phaseVolumeRates() << " " << + limitingConstraint->totalVolumeRate() << " " << limitingConstraint->massRate()); } - - - } - -} - -bool CompositionalMultiphaseWell::evaluateProductionConstraints1( real64 const & time_n, - real64 const & dt, - integer const cycleNumber, - integer const coupledIterationNumber, - DomainPartition & domain, - MeshLevel & mesh, - ElementRegionManager & elemManager, - WellElementSubRegion & subRegion, - DofManager const & dofManager ) -{ - WellControls & wellControls = getWellControls( subRegion ); - - - this->template solveConstraint< MinimumBHPConstraint >( time_n, - dt, - cycleNumber, - coupledIterationNumber, - domain, - mesh, - elemManager, - subRegion, - dofManager ); - - this->template solveConstraint< PhaseProductionConstraint, LiquidProductionConstraint, - MassProductionConstraint, TotalVolProductionConstraint >( time_n, - dt, - cycleNumber, - coupledIterationNumber, - domain, - mesh, - elemManager, - subRegion, - dofManager ); - - this->template selectLimitingConstraint< MinimumBHPConstraint, PhaseProductionConstraint, - MassProductionConstraint, TotalVolProductionConstraint >( time_n, - coupledIterationNumber, - subRegion ); - // this should be done in calculateLImitingConstraint - // wellControls.setControl( static_cast< WellControls::Control >(limitingConstraint->getControl()) ); // old - // wellControls.setCurrentConstraint( limitingConstraint ); // new - WellConstraintBase * limitingConstraint = wellControls.getCurrentConstraint(); - if( coupledIterationNumber < wellControls.estimateSolution() ) - { - - solveNonlinearSystem( time_n, - dt, - cycleNumber, - domain, - mesh, - elemManager, - subRegion, - dofManager ); - - } - limitingConstraint->setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); - limitingConstraint->setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( - CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); - limitingConstraint->setTotalVolumeRate ( wellControls.getReference< real64 >( - CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); - limitingConstraint->setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); - - GEOS_LOG_RANK_0( - " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << limitingConstraint->phaseVolumeRates() << " " << - limitingConstraint->totalVolumeRate() << " " << limitingConstraint->massRate()); - return true; -} - -bool -CompositionalMultiphaseWell:: - evaluateInjectionConstraints( real64 const & time_n, - real64 const & dt, - integer const cycleNumber, - integer const coupledIterationNumber, - DomainPartition & domain, - MeshLevel & mesh, - ElementRegionManager & elemManager, - WellElementSubRegion & subRegion, - DofManager const & dofManager ) -{ - WellControls & wellControls = getWellControls( subRegion ); - - this->template solveConstraint< MaximumBHPConstraint >( time_n, - dt, - cycleNumber, - coupledIterationNumber, - domain, - mesh, - elemManager, - subRegion, - dofManager ); - - this->template solveConstraint< PhaseInjectionConstraint, - MassInjectionConstraint, TotalVolInjectionConstraint >( time_n, - dt, - cycleNumber, - coupledIterationNumber, - domain, - mesh, - elemManager, - subRegion, - dofManager ); - - this->template selectLimitingConstraint< MaximumBHPConstraint, PhaseInjectionConstraint, - MassInjectionConstraint, TotalVolInjectionConstraint >( time_n, - coupledIterationNumber, - subRegion ); - - // this should be done in calculateLimitingCosntraint - //wellControls.setControl( static_cast< WellControls::Control >(limitingConstraint->getControl()) ); // old - //wellControls.setCurrentConstraint( limitingConstraint ); // new - WellConstraintBase * limitingConstraint = wellControls.getCurrentConstraint(); - if( coupledIterationNumber < wellControls.estimateSolution() ) - { - - solveNonlinearSystem( time_n, - dt, - cycleNumber, - domain, - mesh, - elemManager, - subRegion, - dofManager ); } - // Store computed well quantities for this constraint - limitingConstraint->setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); - limitingConstraint->setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( - CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); - limitingConstraint->setTotalVolumeRate ( wellControls.getReference< real64 >( - CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); - limitingConstraint->setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); - GEOS_LOG_RANK_0( - " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << limitingConstraint->phaseVolumeRates() << " " << - limitingConstraint->totalVolumeRate() << " " << limitingConstraint->massRate() ); - return true; -} -bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, - real64 const & dt, - integer const cycleNumber, - integer const coupledIterationNumber, - DomainPartition & domain, - MeshLevel & mesh, - ElementRegionManager & elemManager, - WellElementSubRegion & subRegion, - DofManager const & dofManager ) -{ - WellControls & wellControls = getWellControls( subRegion ); - - bool useEstimator = coupledIterationNumber < wellControls.estimateSolution(); - - if( useEstimator ) + // Check current against other constraints + for( auto & constraint : constraintList ) { - // create list of all constraints to solve - std::vector< std::shared_ptr< WellConstraintBase > > constraintList; - std::shared_ptr< WellConstraintBase > limitingConstraint = nullptr; - if( wellControls.isProducer() ) - { - constraintList = wellControls.getProdRateConstraints(); - // Solve minimum bhp constraint first - limitingConstraint = wellControls.getMinBHPConstraint(); - } - else - { - constraintList = wellControls.getInjRateConstraints(); - // Solve maximum bhp constraint first - limitingConstraint = wellControls.getMaxBHPConstraint(); - } - solveConstraint ( limitingConstraint, time_n, - dt, - cycleNumber, - coupledIterationNumber, - domain, - mesh, - elemManager, - subRegion, - dofManager ); - - for( auto const & constraint : constraintList ) - { - GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), - " Well " << subRegion.getName() << " Constraint " << constraint->getName() << " active " << constraint->isConstraintActive() << - " value " << constraint->getConstraintValue( time_n ) ); - if( constraint->isConstraintActive() && constraint->checkViolation( *limitingConstraint, time_n )) - { - limitingConstraint=constraint; - wellControls.setControl( static_cast< WellControls::Control >(constraint->getControl()) ); // tjb old - wellControls.setCurrentConstraint( limitingConstraint.get() ); - solveConstraint ( constraint, time_n, - dt, - cycleNumber, - coupledIterationNumber, - domain, - mesh, - elemManager, - subRegion, - dofManager ); - // tjb. this is likely not needed. set in update state - constraint->setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); - constraint->setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( - CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); - constraint->setTotalVolumeRate ( wellControls.getReference< real64 >( - CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); - constraint->setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); - - } - } - GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), - " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << limitingConstraint->phaseVolumeRates() << " " << - limitingConstraint->totalVolumeRate() << " " << limitingConstraint->massRate()); - } - else - { - // create list of all constraints to process - std::vector< std::shared_ptr< WellConstraintBase > > constraintList; - if( wellControls.isProducer() ) - { - constraintList = wellControls.getProdRateConstraints(); - // Solve minimum bhp constraint first - constraintList.insert( constraintList.begin(), wellControls.getMinBHPConstraint() ); - } - else - { - constraintList = wellControls.getInjRateConstraints(); - // Solve maximum bhp constraint first; - constraintList.insert( constraintList.begin(), wellControls.getMaxBHPConstraint() ); - } - // Get current constraint - std::shared_ptr< WellConstraintBase > limitingConstraint = nullptr; - for( auto & constraint : constraintList ) + if( limitingConstraint->getName() != constraint->getName()) { - if( constraint->getName() == wellControls.getCurrentConstraint()->getName()) + //std::cout << "Use estimator " << useEstimator << " Evaluating constraint " << constraint.getName() << " against constraint " << + // limitingConstraint->getName() << std::endl; + if( constraint->checkViolation( *limitingConstraint, time_n ) ) { - limitingConstraint = constraint; - // tjb. this is likely not needed. set in update state - constraint->setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); - constraint->setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( - CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); - constraint->setTotalVolumeRate ( wellControls.getReference< real64 >( - CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); - constraint->setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); + wellControls.setControl( static_cast< WellControls::Control >(constraint->getControl()) ); // tjb old + wellControls.setCurrentConstraint( constraint.get() ); GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), - " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << limitingConstraint->phaseVolumeRates() << " " << - limitingConstraint->totalVolumeRate() << " " << limitingConstraint->massRate()); + " Well " << subRegion.getName() << " New Limiting Constraint " << constraint->getName() << " " << constraint->getConstraintValue( time_n ) ); } } - - - // Check current against other constraints - for( auto & constraint : constraintList ) - { - - if( limitingConstraint->getName() != constraint->getName()) - { - //std::cout << "Use estimator " << useEstimator << " Evaluating constraint " << constraint.getName() << " against constraint " << - // limitingConstraint->getName() << std::endl; - if( constraint->checkViolation( *limitingConstraint, time_n ) ) - { - wellControls.setControl( static_cast< WellControls::Control >(constraint->getControl()) ); // tjb old - wellControls.setCurrentConstraint( constraint.get() ); - GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), - " Well " << subRegion.getName() << " New Limiting Constraint " << constraint->getName() << " " << constraint->getConstraintValue( time_n ) ); - } - } - } - GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), - " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << limitingConstraint->phaseVolumeRates() << " " << - limitingConstraint->totalVolumeRate() << " " << limitingConstraint->massRate()); } + GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), + " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << limitingConstraint->phaseVolumeRates() << " " << + limitingConstraint->totalVolumeRate() << " " << limitingConstraint->massRate()); + return true; } REGISTER_CATALOG_ENTRY( PhysicsSolverBase, CompositionalMultiphaseWell, string const &, Group * const ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp index 2edcd74464b..a1aa33be93d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp @@ -445,17 +445,6 @@ class CompositionalMultiphaseWell : public WellSolverBase real64 const & dt, DomainPartition & domain ) override; - - bool evaluateProductionConstraints1( real64 const & time_n, - real64 const & stepDt, - integer const cycleNumber, - integer const coupledIterationNumber, - DomainPartition & domain, - MeshLevel & mesh, - ElementRegionManager & elemManager, - WellElementSubRegion & subRegion, - DofManager const & dofManager ); - virtual bool evaluateConstraints( real64 const & time_n, real64 const & stepDt, integer const cycleNumber, @@ -463,18 +452,7 @@ class CompositionalMultiphaseWell : public WellSolverBase DomainPartition & domain, MeshLevel & mesh, ElementRegionManager & elemManager, - WellElementSubRegion & subRegion, - DofManager const & dofManager ) override; - - virtual bool evaluateInjectionConstraints( real64 const & time_n, - real64 const & stepDt, - integer const cycleNumber, - integer const coupledIterationNumber, - DomainPartition & domain, - MeshLevel & mesh, - ElementRegionManager & elemManager, - WellElementSubRegion & subRegion, - DofManager const & dofManager )override; + WellElementSubRegion & subRegion ) override; private: @@ -502,18 +480,6 @@ class CompositionalMultiphaseWell : public WellSolverBase WellElementSubRegion & subRegion, DofManager const & dofManager ); - template< typename GROUPTYPE, typename ... GROUPTYPES > - void solveConstraint( real64 const & time_n, - real64 const & stepDt, - integer const cycleNumber, - integer const coupledIterationNumber, - DomainPartition & domain, - MeshLevel & mesh, - ElementRegionManager & elemManager, - WellElementSubRegion & subRegion, - DofManager const & dofManager ); - - /// flag indicating whether mass or molar formulation should be used integer m_useMass; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp index 780128bc4b2..6a08cfff591 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp @@ -308,46 +308,6 @@ void WellSolverBase::implicitStepSetup( real64 const & time_n, } -void WellSolverBase::setupWellDofs( DomainPartition & domain ) -{ - if( m_estimatorDoFManager.empty() ) - { - - map< std::pair< string, string >, string_array > meshTargets; - string_array regions; - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, - MeshLevel & meshLevel, - string_array const & regionNames ) - { - ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); - elementRegionManager.forElementRegions< WellElementRegion >( regionNames, - [&]( localIndex const, - WellElementRegion & region ) - { - meshTargets.clear(); - regions.clear(); - regions.emplace_back( region.getName() ); - auto const key = std::make_pair( meshBodyName, meshLevel.getName()); - meshTargets[key] = std::move( regions ); - - DofManager regionDoFManager( region.getName()); - regionDoFManager.setDomain( domain ); - regionDoFManager.addField( wellElementDofName(), - FieldLocation::Elem, - numDofPerWellElement(), - meshTargets ); - - regionDoFManager.addCoupling( wellElementDofName(), - wellElementDofName(), - DofManager::Connector::Node ); - - regionDoFManager.reorderByRank(); - m_estimatorDoFManager.emplace( region.getName(), std::move( regionDoFManager )); - } ); - } ); - } -} - void WellSolverBase::selectWellConstraint( real64 const & time_n, real64 const & dt, const integer cycleNumber, @@ -356,9 +316,6 @@ void WellSolverBase::selectWellConstraint( real64 const & time_n, { GEOS_MARK_FUNCTION; - //GEOS_LOG_RANK( "**** Estimate Well Solution - Start **** " << getName() ); - setupWellDofs( domain ); - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, MeshLevel & meshLevel, string_array const & regionNames ) @@ -389,31 +346,8 @@ void WellSolverBase::selectWellConstraint( real64 const & time_n, if( wellControls.getWellState()) { - //GEOS_LOG_RANK( "**** Estimate Well Solution - Start **** " << subRegion.getName() ); - auto it = m_estimatorDoFManager.find( region.getName()); - if( it == m_estimatorDoFManager.end()) - { - throw std::runtime_error( "DofManager for region " + region.getName() + " not found." ); - } - DofManager & dofManager = it->second; - -// Only build the sparsity pattern if the mesh has changed - Timestamp const meshModificationTimestamp = getMeshModificationTimestamp( domain ); - - if( meshModificationTimestamp > getSystemSetupTimestamp() ) - { - // These are esitmator matrices - setupWellSystem( domain, dofManager, m_localMatrix, m_rhs, m_solution ); - //setSystemSetupTimestamp( meshModificationTimestamp ); - - //std::ostringstream oss; - //m_dofManager.printFieldInfo( oss ); - //GEOS_LOG_LEVEL( logInfo::Fields, oss.str()) - } - - wellControls.setConstraintSwitch( false ); -#if 1 + evaluateConstraints( time_n, dt, cycleNumber, @@ -421,34 +355,8 @@ void WellSolverBase::selectWellConstraint( real64 const & time_n, domain, meshLevel, elementRegionManager, - subRegion, - dofManager ); -#else - if( wellControls.isProducer()) - { - evaluateProductionConstraints( time_n, - dt, - cycleNumber, - coupledIterationNumber, - domain, - meshLevel, - elementRegionManager, - subRegion, - dofManager ); - } - else - { - evaluateInjectionConstraints( time_n, - dt, - cycleNumber, - coupledIterationNumber, - domain, - meshLevel, - elementRegionManager, - subRegion, - dofManager ); - } -#endif + subRegion ); + // If a well is opened and then timestep is cut resulting in the well being shut, if the well is opened // the well initialization code requires control type to by synced integer owner = -1; @@ -461,58 +369,12 @@ void WellSolverBase::selectWellConstraint( real64 const & time_n, WellControls::Control wellControl = wellControls.getControl(); MpiWrapper::broadcast( wellControl, owner ); wellControls.setControl( wellControl ); - - //implicitStepSetup( time_n, dt, domain ); - -// currently the only method is implicit time integration - //real64 const dt_return = nonlinearImplicitStep( time_n, dt, cycleNumber, domain ); - -// final step for completion of timestep. typically secondary variable updates and cleanup. - //implicitStepComplete( time_n, dt_return, domain ); - /* - solveNonlinearSystem( time_n, - dt, - cycleNumber, - domain, - meshLevel, - elementRegionManager, - subRegion, - dofManager ); - */ - - //GEOS_LOG_RANK( "**** Estimate Well Solution End **** " << subRegion.getName()); } - } ); } ); - //GEOS_LOG_RANK( "**** Estimate Well Solution End **** " << getName()); -} - -void WellSolverBase::setupWellSystem( DomainPartition & domain, - DofManager & dofManager, - CRSMatrix< real64, globalIndex > & localMatrix, - ParallelVector & rhs, - ParallelVector & solution, - bool const setSparsity ) -{ - GEOS_MARK_FUNCTION; - - setupWellDofs( domain ); - if( setSparsity ) - { - SparsityPattern< globalIndex > pattern; - dofManager.setSparsityPattern( pattern ); - localMatrix.assimilate< parallelDevicePolicy<> >( std::move( pattern ) ); - } - localMatrix.setName( this->getName() + "/matrix" ); - - rhs.setName( this->getName() + "/rhs" ); - rhs.create( dofManager.numLocalDofs(), MPI_COMM_GEOS ); - - solution.setName( this->getName() + "/solution" ); - solution.create( dofManager.numLocalDofs(), MPI_COMM_GEOS ); } + void WellSolverBase::updateState( DomainPartition & domain ) { GEOS_MARK_FUNCTION; @@ -527,27 +389,6 @@ void WellSolverBase::updateState( DomainPartition & domain ) } ); } -void WellSolverBase::assembleWellSystem( real64 const time_n, - real64 const dt, - ElementRegionManager const & elementRegionManager, - WellElementSubRegion & subRegion, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) -{ - assembleWellAccumulationTerms( time_n, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); - WellControls & wellControls = getWellControls( subRegion ); - if( !wellControls.getConstraintSwitch() ) - { - - assembleWellConstraintTerms( time_n, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); - } - assembleWellPressureRelations( time_n, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); - computeWellPerforationRates( time_n, dt, elementRegionManager, subRegion ); - assembleWellFluxTerms( time_n, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); - -} - void WellSolverBase::assembleSystem( real64 const time, real64 const dt, DomainPartition & domain, @@ -563,8 +404,8 @@ void WellSolverBase::assembleSystem( real64 const time, // iteration // wellEstimator flag > 0 => well esitmator solved for each constraint and then selects the constraint // => estimator solve only performed first "wellEstimator" iterations - - selectWellConstraint( time, dt, 0, geos::currentCoupledNewton, domain ); + NonlinearSolverParameters const & nonlinearParams = getNonlinearSolverParameters(); + selectWellConstraint( time, dt, 0, nonlinearParams.m_numNewtonIterations, domain ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp index 557d360f312..666d4acb270 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp @@ -159,6 +159,13 @@ class WellSolverBase : public PhysicsSolverBase virtual void registerDataOnMesh( Group & meshBodies ) override; + void selectWellConstraint( real64 const & time_n, + real64 const & dt, + integer const cycleNumber, + integer const coupledIterationNumber, + DomainPartition & domain ); + + virtual void setupDofs( DomainPartition const & domain, DofManager & dofManager ) const override; @@ -180,24 +187,6 @@ class WellSolverBase : public PhysicsSolverBase /**@}*/ - /** - * @brief function to assemble the linear system matrix and rhs - * @param time the time at the beginning of the step - * @param dt the desired timestep - * @param domain the domain partition - * @param dofManager degree-of-freedom manager associated with the linear system - * @param matrix the system matrix - * @param rhs the system right-hand side vector - */ - - void assembleWellSystem( real64 const time, - real64 const dt, - ElementRegionManager const & elementRegionManager, - WellElementSubRegion & subRegion, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ); - virtual void assembleSystem( real64 const time, real64 const dt, DomainPartition & domain, @@ -315,14 +304,6 @@ class WellSolverBase : public PhysicsSolverBase WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), DofManager const & GEOS_UNUSED_PARAM( dofManager ), arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localRhs ) ) {return std::numeric_limits< real64 >::max();}; - bool solveNonlinearSystem( real64 const & time_n, - real64 const & stepDt, - integer const cycleNumber, - DomainPartition & domain, - MeshLevel & mesh, - ElementRegionManager & elementRegionManager, - WellElementSubRegion & subregion, - DofManager const & dofManager ); virtual real64 scalingForWellSystemSolution( ElementSubRegionBase & GEOS_UNUSED_PARAM( subRegion ), @@ -449,28 +430,9 @@ class WellSolverBase : public PhysicsSolverBase DomainPartition & GEOS_UNUSED_PARAM( domain ), MeshLevel & GEOS_UNUSED_PARAM( mesh ), ElementRegionManager & GEOS_UNUSED_PARAM( elemManager ), - WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ), - DofManager const & GEOS_UNUSED_PARAM( dofManager ) ) { return false;}; - - virtual bool evaluateProductionConstraints( real64 const & GEOS_UNUSED_PARAM( time_n ), - real64 const & GEOS_UNUSED_PARAM( stepDt ), - integer const GEOS_UNUSED_PARAM( cycleNumber ), - integer const GEOS_UNUSED_PARAM( coupledIterationNumber ), - DomainPartition & GEOS_UNUSED_PARAM( domain ), - MeshLevel & GEOS_UNUSED_PARAM( mesh ), - ElementRegionManager & GEOS_UNUSED_PARAM( elemManager ), - WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ), - DofManager const & GEOS_UNUSED_PARAM( dofManager ) ) { return false;}; - - virtual bool evaluateInjectionConstraints( real64 const & GEOS_UNUSED_PARAM( time_n ), - real64 const & GEOS_UNUSED_PARAM( stepDt ), - integer const GEOS_UNUSED_PARAM( cycleNumber ), - integer const GEOS_UNUSED_PARAM( coupledIterationNumber ), - DomainPartition & GEOS_UNUSED_PARAM( domain ), - MeshLevel & GEOS_UNUSED_PARAM( mesh ), - ElementRegionManager & GEOS_UNUSED_PARAM( elemManager ), - WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ), - DofManager const & GEOS_UNUSED_PARAM( dofManager ) ) {return true;}; + WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion )) { return false;}; + + /// name of the flow solver string m_flowSolverName; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/PerforationFluxKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/PerforationFluxKernels.hpp index 18a48ee1e63..e8862990a2d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/PerforationFluxKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/PerforationFluxKernels.hpp @@ -569,7 +569,7 @@ class PerforationFluxKernelFactory string const flowSolverName, PerforationData * const perforationData, ElementSubRegionBase const & subRegion, - ElementRegionManager & elemManager, + ElementRegionManager const & elemManager, bool const isInjector, bool const isCrossflowEnabled ) { @@ -848,7 +848,7 @@ class PerforationFluxKernelFactory PerforationData * const perforationData, ElementSubRegionBase const & subRegion, MultiFluidBase const & fluid, - ElementRegionManager & elemManager, + ElementRegionManager const & elemManager, bool const isInjector, bool const isCrossflowEnabled ) { From 48aabd41b261cb4ec2b35506c7ed033d607bde15 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 30 Sep 2025 07:58:50 -0700 Subject: [PATCH 04/71] rel mode fix --- .../fluidFlow/wells/CompositionalMultiphaseWell.cpp | 6 ------ .../fluidFlow/wells/CompositionalMultiphaseWell.hpp | 6 ------ .../fluidFlow/wells/WellSolverBase.cpp | 13 ++++--------- .../fluidFlow/wells/WellSolverBase.hpp | 7 ------- 4 files changed, 4 insertions(+), 28 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index c4aa752a4bb..18d5becd9f1 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -3196,12 +3196,6 @@ void CompositionalMultiphaseWell::printRates( real64 const & time_n, bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, - real64 const & dt, - integer const cycleNumber, - integer const coupledIterationNumber, - DomainPartition & domain, - MeshLevel & mesh, - ElementRegionManager & elemManager, WellElementSubRegion & subRegion ) { WellControls & wellControls = getWellControls( subRegion ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp index a1aa33be93d..2001dc95fa1 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp @@ -446,12 +446,6 @@ class CompositionalMultiphaseWell : public WellSolverBase DomainPartition & domain ) override; virtual bool evaluateConstraints( real64 const & time_n, - real64 const & stepDt, - integer const cycleNumber, - integer const coupledIterationNumber, - DomainPartition & domain, - MeshLevel & mesh, - ElementRegionManager & elemManager, WellElementSubRegion & subRegion ) override; private: diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp index 6a08cfff591..aee41ffafbf 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp @@ -310,12 +310,13 @@ void WellSolverBase::implicitStepSetup( real64 const & time_n, void WellSolverBase::selectWellConstraint( real64 const & time_n, real64 const & dt, - const integer cycleNumber, const integer coupledIterationNumber, DomainPartition & domain ) { GEOS_MARK_FUNCTION; - + GEOS_UNUSED_VAR(dt); + GEOS_UNUSED_VAR(coupledIterationNumber); + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, MeshLevel & meshLevel, string_array const & regionNames ) @@ -349,12 +350,6 @@ void WellSolverBase::selectWellConstraint( real64 const & time_n, wellControls.setConstraintSwitch( false ); evaluateConstraints( time_n, - dt, - cycleNumber, - coupledIterationNumber, - domain, - meshLevel, - elementRegionManager, subRegion ); // If a well is opened and then timestep is cut resulting in the well being shut, if the well is opened @@ -405,7 +400,7 @@ void WellSolverBase::assembleSystem( real64 const time, // wellEstimator flag > 0 => well esitmator solved for each constraint and then selects the constraint // => estimator solve only performed first "wellEstimator" iterations NonlinearSolverParameters const & nonlinearParams = getNonlinearSolverParameters(); - selectWellConstraint( time, dt, 0, nonlinearParams.m_numNewtonIterations, domain ); + selectWellConstraint( time, dt, nonlinearParams.m_numNewtonIterations, domain ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp index 666d4acb270..d9b5c49f6c4 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp @@ -161,7 +161,6 @@ class WellSolverBase : public PhysicsSolverBase void selectWellConstraint( real64 const & time_n, real64 const & dt, - integer const cycleNumber, integer const coupledIterationNumber, DomainPartition & domain ); @@ -424,12 +423,6 @@ class WellSolverBase : public PhysicsSolverBase DomainPartition & domain ) = 0; virtual bool evaluateConstraints( real64 const & GEOS_UNUSED_PARAM( time_n ), - real64 const & GEOS_UNUSED_PARAM( stepDt ), - integer const GEOS_UNUSED_PARAM( cycleNumber ), - integer const GEOS_UNUSED_PARAM( coupledIterationNumber ), - DomainPartition & GEOS_UNUSED_PARAM( domain ), - MeshLevel & GEOS_UNUSED_PARAM( mesh ), - ElementRegionManager & GEOS_UNUSED_PARAM( elemManager ), WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion )) { return false;}; From a85ee1d60b4f84084c139398e6474657490216bd Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Thu, 2 Oct 2025 12:04:47 -0700 Subject: [PATCH 05/71] 1) remove old code, 2) test different constraint org, 3) singlephase broken --- .../wells/CompositionalMultiphaseWell.cpp | 172 +-------- .../wells/CompositionalMultiphaseWell.hpp | 5 - .../fluidFlow/wells/WellConstants.hpp | 5 + .../fluidFlow/wells/WellConstraintsBase.cpp | 62 +++ .../fluidFlow/wells/WellConstraintsBase.hpp | 149 ++++++++ .../fluidFlow/wells/WellControls.cpp | 357 ++---------------- .../fluidFlow/wells/WellControls.hpp | 209 +++------- .../wells/WellPhaseRateConstraints.cpp | 59 +++ .../wells/WellPhaseRateConstraints.hpp | 162 +++++++- .../fluidFlow/wells/WellSolverBase.cpp | 6 +- .../wells/WellTotalVolRateConstraints.cpp | 8 - .../CompositionalMultiphaseWellKernels.cpp | 189 +++------- .../CompositionalMultiphaseWellKernels.hpp | 66 ++-- ...rmalCompositionalMultiphaseWellKernels.hpp | 56 +-- .../wells/kernels/WellConstraintKernels.hpp | 2 +- 15 files changed, 631 insertions(+), 876 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 18d5becd9f1..cf3c3f7ab3c 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -397,49 +397,14 @@ void CompositionalMultiphaseWell::validateConstitutiveModels( DomainPartition co } ); } -void CompositionalMultiphaseWell::validateInjectionStreams( WellElementSubRegion const & subRegion ) const -{ - WellControls const & wellControls = getWellControls( subRegion ); - - // check well injection stream for injectors - if( wellControls.isInjector()) - { - arrayView1d< real64 const > const & injectionStream = wellControls.getInjectionStream(); - integer const streamSize = injectionStream.size(); - GEOS_THROW_IF( ( streamSize == 0 ), - "WellControls " << wellControls.getName() << - " : Injection stream not specified for well " << subRegion.getName(), - InputError ); - GEOS_THROW_IF( ( streamSize != m_numComponents ), - "WellControls " << wellControls.getName() << - " : Injection stream for well " << subRegion.getName() << " should have " << - m_numComponents << " components.", - InputError ); - - real64 compFracSum = 0; - for( integer ic = 0; ic < m_numComponents; ++ic ) - { - real64 const compFrac = injectionStream[ic]; - GEOS_THROW_IF( ( compFrac < 0.0 ) || ( compFrac > 1.0 ), - "WellControls " << wellControls.getDataContext() << - ": Invalid injection stream for well " << subRegion.getName(), - InputError ); - compFracSum += compFrac; - } - GEOS_THROW_IF( ( compFracSum < 1.0 - std::numeric_limits< real64 >::epsilon() ) || - ( compFracSum > 1.0 + std::numeric_limits< real64 >::epsilon() ), - "WellControls " << wellControls.getDataContext() << - ": Invalid injection stream for well " << subRegion.getName(), - InputError ); - } -} void CompositionalMultiphaseWell::validateWellConstraints( real64 const & time_n, real64 const & GEOS_UNUSED_PARAM( dt ), WellElementSubRegion const & subRegion, ElementRegionManager const & elemManager ) { + GEOS_UNUSED_VAR(time_n); WellControls & wellControls = getWellControls( subRegion ); if( !wellControls.useSurfaceConditions() ) { @@ -486,65 +451,7 @@ void CompositionalMultiphaseWell::validateWellConstraints( real64 const & time_n } ); - // now that we know we are single-phase, we can check a few things in the constraints - - WellControls::Control const currentControl = wellControls.getControl(); - real64 const & targetTotalRate = wellControls.getTargetTotalRate( time_n ); - real64 const & targetPhaseRate = wellControls.getTargetPhaseRate( time_n ); - real64 const & targetMassRate = wellControls.getTargetMassRate( time_n ); - - GEOS_THROW_IF( wellControls.isInjector() && currentControl == WellControls::Control::PHASEVOLRATE, - "WellControls " << wellControls.getDataContext() << - ": Phase rate control is not available for injectors", - InputError ); - GEOS_THROW_IF( wellControls.isProducer() && currentControl == WellControls::Control::TOTALVOLRATE, - "WellControls " << wellControls.getDataContext() << - ": Total rate control is not available for producers", - InputError ); - - GEOS_THROW_IF( wellControls.isInjector() && targetTotalRate < 0.0, - "WellControls " << wellControls.getDataContext() << - ": Target total rate cannot be negative for injectors", - InputError ); - GEOS_THROW_IF( wellControls.isInjector() && !isZero( targetPhaseRate ), - "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, - "WellControls " << wellControls.getDataContext() << - ": Target phase rate cannot be negative for producers", - InputError ); - GEOS_THROW_IF( wellControls.isProducer() && !isZero( targetTotalRate ), - "WellControls " << wellControls.getDataContext() << - ": Target total rate cannot be used for producers", - InputError ); - - // Find target phase index for phase rate constraint - for( integer ip = 0; ip < fluid.numFluidPhases(); ++ip ) - { - if( fluid.phaseNames()[ip] == wellControls.getTargetPhaseName() ) - { - m_targetPhaseIndex = ip; - } - } - GEOS_THROW_IF( wellControls.isProducer() && m_targetPhaseIndex == -1, - "WellControls " << wellControls.getDataContext() << - ": Phase " << wellControls.getTargetPhaseName() << " not found for well control " << wellControls.getName(), - InputError ); + } void CompositionalMultiphaseWell::initializePostSubGroups() @@ -555,16 +462,6 @@ void CompositionalMultiphaseWell::initializePostSubGroups() validateConstitutiveModels( domain ); - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - validateInjectionStreams( subRegion ); - } ); - } ); } void CompositionalMultiphaseWell::initializePostInitialConditionsPreSubGroups() @@ -1413,7 +1310,6 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh compositionalMultiphaseWellKernels:: RateInitializationKernel:: launch( subRegion.size(), - m_targetPhaseIndex, wellControls, time_n, // initialization done at time_n wellElemPhaseDens, @@ -1763,7 +1659,6 @@ CompositionalMultiphaseWell::calculateWellResidualNorm( real64 const & time_n, thermalCompositionalMultiphaseWellKernels::ResidualNormKernelFactory:: createAndLaunch< parallelDevicePolicy<> >( m_numComponents, - m_targetPhaseIndex, rankOffset, wellDofKey, localRhs, @@ -1791,7 +1686,6 @@ CompositionalMultiphaseWell::calculateWellResidualNorm( real64 const & time_n, compositionalMultiphaseWellKernels::ResidualNormKernelFactory:: createAndLaunch< parallelDevicePolicy<> >( m_numComponents, numDofPerWellElement(), - m_targetPhaseIndex, rankOffset, wellDofKey, localRhs, @@ -1897,7 +1791,6 @@ CompositionalMultiphaseWell::calculateResidualNorm( real64 const & time_n, thermalCompositionalMultiphaseWellKernels::ResidualNormKernelFactory:: createAndLaunch< parallelDevicePolicy<> >( m_numComponents, - m_targetPhaseIndex, rankOffset, wellDofKey, localRhs, @@ -1925,7 +1818,6 @@ CompositionalMultiphaseWell::calculateResidualNorm( real64 const & time_n, compositionalMultiphaseWellKernels::ResidualNormKernelFactory:: createAndLaunch< parallelDevicePolicy<> >( m_numComponents, numDofPerWellElement(), - m_targetPhaseIndex, rankOffset, wellDofKey, localRhs, @@ -2780,7 +2672,7 @@ void CompositionalMultiphaseWell::assembleWellConstraintTerms( real64 const & ti } -void CompositionalMultiphaseWell::assembleWellPressureRelations( real64 const & time_n, +void CompositionalMultiphaseWell::assembleWellPressureRelations( real64 const & GEOS_UNUSED_PARAM(time_n), real64 const & GEOS_UNUSED_PARAM( dt ), WellElementSubRegion const & subRegion, DofManager const & dofManager, @@ -2826,11 +2718,6 @@ void CompositionalMultiphaseWell::assembleWellPressureRelations( real64 const & isThermal, subRegion.size(), dofManager.rankOffset(), - subRegion.isLocallyOwned(), - subRegion.getTopWellElementIndex(), - m_targetPhaseIndex, - wellControls, - time_n, // controls evaluated with BHP/rate of the beginning of step elemStatus, wellElemDofNumber, wellElemGravCoef, @@ -2842,53 +2729,6 @@ void CompositionalMultiphaseWell::assembleWellPressureRelations( real64 const & localMatrix, localRhs ); - if( controlHasSwitched ) - { - // TODO: move the switch logic into wellControls - // TODO: implement a more general switch when more then two constraints per well type are allowed - - if( wellControls.getControl() == WellControls::Control::BHP ) - { - if( wellControls.isProducer() ) - { - wellControls.switchToPhaseRateControl( wellControls.getTargetPhaseRate( time_n ) ); - GEOS_LOG_LEVEL_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( time_n ) ); - GEOS_LOG_LEVEL_RANK_0( logInfo::WellControl, - GEOS_FMT( "Control switch for well {} from BHP constraint to mass rate constraint", subRegion.getName()) ); - } - else - { - wellControls.switchToTotalRateControl( wellControls.getTargetTotalRate( time_n ) ); - GEOS_LOG_LEVEL_RANK_0( logInfo::WellControl, - GEOS_FMT( "Control switch for well {} from BHP constraint to total volumetric rate constraint", subRegion.getName()) ); - } - } - else - { - wellControls.switchToBHPControl( wellControls.getTargetBHP( time_n ) ); - GEOS_LOG_LEVEL_RANK_0( logInfo::WellControl, - GEOS_FMT( "Control switch for well {} from rate constraint to BHP constraint", subRegion.getName() ) ); - } - } - - // If a well is opened and then timestep is cut resulting in the well being shut, if the well is opened - // the well initialization code requires control type to by synced - integer owner = -1; - // Only subregion owner evaluates well control and control changes need to be broadcast to all ranks - if( subRegion.isLocallyOwned() ) - { - owner = MpiWrapper::commRank( MPI_COMM_GEOS ); - } - owner = MpiWrapper::max( owner ); - WellControls::Control wellControl = wellControls.getControl(); - MpiWrapper::broadcast( wellControl, owner ); - wellControls.setControl( wellControl ); - } } @@ -3200,7 +3040,7 @@ bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, { WellControls & wellControls = getWellControls( subRegion ); // create list of all constraints to process - std::vector< std::shared_ptr< WellConstraintBase > > constraintList; + std::vector< WellConstraintBase * > constraintList; if( wellControls.isProducer() ) { constraintList = wellControls.getProdRateConstraints(); @@ -3214,7 +3054,7 @@ bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, constraintList.insert( constraintList.begin(), wellControls.getMaxBHPConstraint() ); } // Get current constraint - std::shared_ptr< WellConstraintBase > limitingConstraint = nullptr; + WellConstraintBase * limitingConstraint = nullptr; for( auto & constraint : constraintList ) { if( constraint->getName() == wellControls.getCurrentConstraint()->getName()) @@ -3245,7 +3085,7 @@ bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, if( constraint->checkViolation( *limitingConstraint, time_n ) ) { wellControls.setControl( static_cast< WellControls::Control >(constraint->getControl()) ); // tjb old - wellControls.setCurrentConstraint( constraint.get() ); + wellControls.setCurrentConstraint( constraint ); GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), " Well " << subRegion.getName() << " New Limiting Constraint " << constraint->getName() << " " << constraint->getConstraintValue( time_n ) ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp index 2001dc95fa1..6a8998fca4f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp @@ -418,11 +418,6 @@ class CompositionalMultiphaseWell : public WellSolverBase void validateWellControlsForFluid( WellControls const & wellControls, constitutive::MultiFluidBase const & fluid ) const; - /** - * @brief Checks injection streams for validity (compositions sum to one) - * @param subRegion the well subRegion - */ - void validateInjectionStreams( WellElementSubRegion const & subRegion ) const; /** * @brief Make sure that the well constraints are compatible diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstants.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstants.hpp index 58b8b421c3a..83eadb7c2ff 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstants.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstants.hpp @@ -36,6 +36,11 @@ struct WellConstants static constexpr real64 defaultInjectorBHP = 1.01325e8; }; +enum class WellTypes : integer +{ + PRODUCER, /**< A production well */ + INJECTOR /**< An injection well */ +}; } //namespace geos #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTANTS_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp index 9fcc01525c3..626b486c436 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp @@ -134,4 +134,66 @@ void WellConstraintBase::setNextDtFromTable( TableFunction const * table, real64 } } +// *** Phase Constraint for Injection Well *************************************************************** +ProductionConstraint::ProductionConstraint( string const & name, Group * const parent ) + : WellConstraintBase( name, parent ) +{} + +ProductionConstraint::~ProductionConstraint() +{} + +void ProductionConstraint::postInputInitialization() +{ + // Validate value and table options + WellConstraintBase::postInputInitialization(); + +} + +// *** Phase Constraint for Injection Well *************************************************************** +InjectionConstraint::InjectionConstraint( string const & name, Group * const parent ) + : WellConstraintBase( name, parent ) +{ + registerWrapper( injectionStreamKey::injectionStreamString(), &m_injectionStream ). + setDefaultValue( -1 ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Global component densities of the injection stream [moles/m^3 or kg/m^3]" ); + + registerWrapper( injectionStreamKey::injectionTemperatureString(), &m_injectionTemperature ). + setDefaultValue( -1 ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Temperature of the injection stream [K]" ); +} + +InjectionConstraint::~InjectionConstraint() +{} + +void InjectionConstraint::postInputInitialization() +{ + // Validate value and table options + WellConstraintBase::postInputInitialization(); + +// Validate the injection stream and temperature + validateInjectionStream( ); + +} + +void InjectionConstraint::validateInjectionStream( ) +{ + if( !m_injectionStream.empty()) + { + real64 sum = 0.0; + for( localIndex ic = 0; ic < m_injectionStream.size(); ++ic ) + { + GEOS_ERROR_IF( m_injectionStream[ic] < 0.0 || m_injectionStream[ic] > 1.0, + getWrapperDataContext( injectionStreamKey::injectionStreamString() ) << ": Invalid injection stream" ); + sum += m_injectionStream[ic]; + } + GEOS_THROW_IF( LvArray::math::abs( 1.0 - sum ) > std::numeric_limits< real64 >::epsilon(), + getWrapperDataContext( injectionStreamKey::injectionStreamString() ) << ": Invalid injection stream", + InputError ); + } +} + + } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp index 51527811935..781ee973f07 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp @@ -415,6 +415,155 @@ class WellConstraintBase : public dataRepository::Group real64 m_rateSign; }; +/** + * @class ProductionConstraint + * @brief This class describes constraint used to control a production well. + */ + +class ProductionConstraint : public WellConstraintBase +{ +public: + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for WellControls Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit ProductionConstraint( string const & name, dataRepository::Group * const parent ); + + /** + * @brief Default destructor. + */ + ~ProductionConstraint() override; + + /** + * @brief Deleted default constructor. + */ + ProductionConstraint() = delete; + + /** + * @brief Deleted copy constructor. + */ + ProductionConstraint( ProductionConstraint const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + ProductionConstraint( ProductionConstraint && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + ProductionConstraint & operator=( ProductionConstraint const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + ProductionConstraint & operator=( ProductionConstraint && ) = delete; + + ///@} + +protected: + + virtual void postInputInitialization() override; + + +}; + +/** + * @class InjectionConstraint + * @brief This class describes constraint used to control a injection well. + */ + +class InjectionConstraint : public WellConstraintBase +{ +public: + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for WellControls Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit InjectionConstraint( string const & name, dataRepository::Group * const parent ); + + /** + * @brief Default destructor. + */ + ~InjectionConstraint() override; + + /** + * @brief Deleted default constructor. + */ + InjectionConstraint() = delete; + + /** + * @brief Deleted copy constructor. + */ + InjectionConstraint( InjectionConstraint const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + InjectionConstraint( InjectionConstraint && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + InjectionConstraint & operator=( InjectionConstraint const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + InjectionConstraint & operator=( InjectionConstraint && ) = delete; + + ///@} + + struct injectionStreamKey + { + /// String key for the well injection stream + static constexpr char const * injectionStreamString() { return "injectionStream"; } + /// String key for the well injection temperature + static constexpr char const * injectionTemperatureString() { return "injectionTemperature"; } + }; + + /** + * @brief Const accessor for the composition of the injection stream + * @return a global component fraction vector + */ + arrayView1d< real64 const > getInjectionStream() const { return m_injectionStream; } + + /** + * @brief Const accessor for the temperature of the injection stream + * @return the temperature of the injection stream + */ + real64 getInjectionTemperature() const { return m_injectionTemperature; } + +protected: + + virtual void postInputInitialization() override; + + void validateInjectionStream(); +private: + + /// Vector with global component fractions at the injector + array1d< real64 > m_injectionStream; + + /// Temperature at the injector + real64 m_injectionTemperature; + +}; } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index 2b271873b58..160004383d0 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -32,23 +32,13 @@ using namespace dataRepository; WellControls::WellControls( string const & name, Group * const parent ) : Group( name, parent ), m_type( Type::PRODUCER ), - m_refElevation( 0.0 ), // tjb remove - m_refGravCoef( 0.0 ), // tjb remove - m_inputControl( Control::UNINITIALIZED ), // tjb remove m_currentControl( Control::UNINITIALIZED ), // tjb remove - m_targetBHP( 0.0 ), - m_targetTotalRate( 0.0 ), // tjb remove - m_targetPhaseRate( 0.0 ), // tjb remove - m_targetMassRate( 0.0 ), // tjb remove m_useSurfaceConditions( 0 ), m_surfacePres( -1.0 ), m_surfaceTemp( -1.0 ), m_isCrossflowEnabled( 1 ), m_initialPressureCoefficient( 0.1 ), m_rateSign( -1.0 ), - m_targetTotalRateTable( nullptr ), // tjb remove - m_targetPhaseRateTable( nullptr ), // tjb remove - m_targetBHPTable( nullptr ), // tjb remove m_statusTable( nullptr ), m_wellOpen( false ), m_estimateSolution( 0 ), @@ -63,61 +53,12 @@ WellControls::WellControls( string const & name, Group * const parent ) setInputFlag( InputFlags::REQUIRED ). setDescription( "Well type. Valid options:\n* " + EnumStrings< Type >::concat( "\n* " ) ); - registerWrapper( viewKeyStruct::inputControlString(), &m_inputControl ). - setInputFlag( InputFlags::REQUIRED ). - setDescription( "Well control. Valid options:\n* " + EnumStrings< Control >::concat( "\n* " ) ); - registerWrapper( viewKeyStruct::currentControlString(), &m_currentControl ). setDefaultValue( Control::UNINITIALIZED ). setInputFlag( InputFlags::FALSE ). setDescription( "Current well control" ); - 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 ). - setDefaultValue( -1 ). - setInputFlag( InputFlags::REQUIRED ). - setDescription( "Reference elevation where BHP control is enforced [m]" ); - - registerWrapper( viewKeyStruct::injectionStreamString(), &m_injectionStream ). - setDefaultValue( -1 ). - setSizedFromParent( 0 ). - setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Global component densities of the injection stream [moles/m^3 or kg/m^3]" ); - registerWrapper( viewKeyStruct::injectionTemperatureString(), &m_injectionTemperature ). - setDefaultValue( -1 ). - setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Temperature of the injection stream [K]" ); registerWrapper( viewKeyStruct::useSurfaceConditionsString(), &m_useSurfaceConditions ). setDefaultValue( 0 ). @@ -158,37 +99,6 @@ WellControls::WellControls( string const & name, Group * const parent ) " - Injector pressure at reference depth initialized as: (1+initialPressureCoefficient)*reservoirPressureAtClosestPerforation + density*g*( zRef - zPerf ) \n" " - Producer pressure at reference depth initialized as: (1-initialPressureCoefficient)*reservoirPressureAtClosestPerforation + density*g*( zRef - zPerf ) " ); - registerWrapper( viewKeyStruct::targetBHPTableNameString(), &m_targetBHPTableName ). - setRTTypeName( rtTypes::CustomTypes::groupNameRef ). - setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Name of the BHP table when the rate is a time dependent function" ); - - registerWrapper( viewKeyStruct::targetTotalRateTableNameString(), &m_targetTotalRateTableName ). - setRTTypeName( rtTypes::CustomTypes::groupNameRef ). - setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Name of the total rate table when the rate is a time dependent function" ); - - registerWrapper( viewKeyStruct::targetPhaseRateTableNameString(), &m_targetPhaseRateTableName ). - setRTTypeName( rtTypes::CustomTypes::groupNameRef ). - setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Name of the phase rate table when the rate is a time dependent function" ); - - registerWrapper( viewKeyStruct::targetMassRateTableNameString(), &m_targetMassRateTableName ). - setRTTypeName( rtTypes::CustomTypes::groupNameRef ). - setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Name of the mass rate table when the rate is a time dependent function" ); - - registerWrapper( viewKeyStruct::statusTableNameString(), &m_statusTableName ). - setRTTypeName( rtTypes::CustomTypes::groupNameRef ). - setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Name of the well status table when the status of the well is a time dependent function. \n" - "If the status function evaluates to a positive value at the current time, the well will be open otherwise the well will be shut." ); - - - this->registerWrapper( viewKeyStruct::estimateWellSolutionString(), &m_estimateSolution ). - setApplyDefaultValue( 0 ). - setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Flag to esitmate well solution prior to coupled reservoir and well solve." ); addLogLevel< logInfo::WellControl >(); } @@ -208,56 +118,58 @@ Group * WellControls::createChild( string const & childKey, string const & child if( childKey == viewKeyStruct::minimumBHPConstraintString() ) { MinimumBHPConstraint & bhpConstraint = registerGroup< MinimumBHPConstraint >( childName ); - m_minBHPConstraint = std::shared_ptr< MinimumBHPConstraint >( &bhpConstraint ); + m_minBHPConstraint = &bhpConstraint; constraint = &bhpConstraint; } else if( childKey == viewKeyStruct::maximumBHPConstraintString() ) { MaximumBHPConstraint & bhpConstraint = registerGroup< MaximumBHPConstraint >( childName ); - m_maxBHPConstraint = std::shared_ptr< MaximumBHPConstraint >( &bhpConstraint ); + m_maxBHPConstraint = &bhpConstraint; constraint = &bhpConstraint; } else if( childKey == viewKeyStruct::phaseProductionConstraintString() ) { - PhaseProductionConstraint & phaseConstraint = registerGroup< PhaseProductionConstraint >( childName ); - m_productionRateConstraintList.emplace_back( std::shared_ptr< WellConstraintBase >( &phaseConstraint ) ); + //PhaseProductionConstraint & phaseConstraint = registerGroup< PhaseProductionConstraint >( childName ); + PhaseProductionConstraint1 & phaseConstraint = registerGroup< PhaseProductionConstraint1 >( childName ); + m_productionRateConstraintList.emplace_back( &phaseConstraint ); constraint = &phaseConstraint; } else if( childKey == viewKeyStruct::phaseInjectionConstraintString() ) { - PhaseInjectionConstraint & phaseConstraint = registerGroup< PhaseInjectionConstraint >( childName ); - m_injectionRateConstraintList.emplace_back( std::shared_ptr< WellConstraintBase >( &phaseConstraint ) ); + //PhaseInjectionConstraint & phaseConstraint = registerGroup< PhaseInjectionConstraint >( childName ); + PhaseInjectionConstraint1 & phaseConstraint = registerGroup< PhaseInjectionConstraint1 >( childName ); + m_injectionRateConstraintList.emplace_back( &phaseConstraint ); constraint = &phaseConstraint; } else if( childKey == viewKeyStruct::totalVolProductionConstraintString() ) { TotalVolProductionConstraint & volConstraint = registerGroup< TotalVolProductionConstraint >( childName ); - m_productionRateConstraintList.emplace_back( std::shared_ptr< WellConstraintBase >( &volConstraint ) ); + m_productionRateConstraintList.emplace_back( &volConstraint ); constraint = &volConstraint; } else if( childKey == viewKeyStruct::totalVolInjectionConstraintString() ) { TotalVolInjectionConstraint & volConstraint = registerGroup< TotalVolInjectionConstraint >( childName ); - m_injectionRateConstraintList.emplace_back( std::shared_ptr< WellConstraintBase >( &volConstraint ) ); + m_injectionRateConstraintList.emplace_back( &volConstraint ); constraint = &volConstraint; } else if( childKey == viewKeyStruct::massProductionConstraintString() ) { MassProductionConstraint & massConstraint = registerGroup< MassProductionConstraint >( childName ); - m_productionRateConstraintList.emplace_back( std::shared_ptr< WellConstraintBase >( &massConstraint ) ); + m_productionRateConstraintList.emplace_back( &massConstraint ); constraint = &massConstraint; } else if( childKey == viewKeyStruct::massInjectionConstraintString() ) { MassInjectionConstraint & massConstraint = registerGroup< MassInjectionConstraint >( childName ); - m_injectionRateConstraintList.emplace_back( std::shared_ptr< WellConstraintBase >( &massConstraint ) ); + m_injectionRateConstraintList.emplace_back( &massConstraint ); constraint = &massConstraint; } else if( childKey == viewKeyStruct::liquidProductionConstraintString() ) { LiquidProductionConstraint & liquidConstraint = registerGroup< LiquidProductionConstraint >( childName ); - m_productionRateConstraintList.emplace_back( std::shared_ptr< LiquidProductionConstraint >( &liquidConstraint ) ); + m_productionRateConstraintList.emplace_back( &liquidConstraint ); constraint = &liquidConstraint; } return constraint; @@ -268,30 +180,6 @@ void WellControls::expandObjectCatalogs() //createChild( keys::wellControls, keys::wellControls ); } -void WellControls::switchToBHPControl( real64 const & val ) -{ - m_currentControl = Control::BHP; - m_targetBHP = val; -} - -void WellControls::switchToTotalRateControl( real64 const & val ) -{ - m_currentControl = Control::TOTALVOLRATE; - m_targetTotalRate = val; -} - -void WellControls::switchToPhaseRateControl( real64 const & val ) -{ - m_currentControl = Control::PHASEVOLRATE; - m_targetPhaseRate = val; -} - -void WellControls::switchToMassRateControl( real64 const & val ) -{ - m_currentControl = Control::MASSRATE; - m_targetMassRate = val; -} - namespace { @@ -317,44 +205,6 @@ TableFunction * createWellTable( string const & tableName, void WellControls::postInputInitialization() { - // 0) Assign the value of the current well control - // When the simulation starts from a restart file, we don't want to use the inputControl, - // because the control may have switched in the simulation that generated the restart - GEOS_THROW_IF( m_inputControl == Control::UNINITIALIZED, - getWrapperDataContext( viewKeyStruct::inputControlString() ) << - ": Input well control cannot be uninitialized", - InputError ); - - if( m_currentControl == Control::UNINITIALIZED ) - { - m_currentControl = m_inputControl; - } - - // 1.a) check target BHP - GEOS_THROW_IF( m_targetBHP < 0, - getWrapperDataContext( viewKeyStruct::targetBHPString() ) << - ": Target bottom-hole pressure is negative", - InputError ); - - // 1.b) check target rates - GEOS_THROW_IF( m_targetTotalRate < 0, - getWrapperDataContext( viewKeyStruct::targetTotalRateString() ) << ": Target rate is negative", - InputError ); - - GEOS_THROW_IF( m_targetPhaseRate < 0, - getWrapperDataContext( viewKeyStruct::targetPhaseRateString() ) << ": Target oil rate is negative", - InputError ); - - GEOS_THROW_IF( m_targetMassRate < 0, - getWrapperDataContext( viewKeyStruct::targetMassRateString() ) << ": Target mass rate is negative", - InputError ); - - GEOS_THROW_IF( (m_injectionStream.empty() && m_injectionTemperature >= 0) || - (!m_injectionStream.empty() && m_injectionTemperature < 0), - "WellControls " << getDataContext() << ": Both " - << viewKeyStruct::injectionStreamString() << " and " << viewKeyStruct::injectionTemperatureString() - << " must be specified for multiphase simulations", - InputError ); // 1.c) Set the multiplier for the rates if( isProducer() ) @@ -366,104 +216,16 @@ void WellControls::postInputInitialization() m_rateSign = 1.0; } - // 2) check injection stream - if( !m_injectionStream.empty()) - { - real64 sum = 0.0; - for( localIndex ic = 0; ic < m_injectionStream.size(); ++ic ) - { - GEOS_ERROR_IF( m_injectionStream[ic] < 0.0 || m_injectionStream[ic] > 1.0, - getWrapperDataContext( viewKeyStruct::injectionStreamString() ) << ": Invalid injection stream" ); - sum += m_injectionStream[ic]; - } - GEOS_THROW_IF( LvArray::math::abs( 1.0 - sum ) > std::numeric_limits< real64 >::epsilon(), - getWrapperDataContext( viewKeyStruct::injectionStreamString() ) << ": Invalid injection stream", - InputError ); - } - // 3) check the flag for surface / reservoir conditions GEOS_THROW_IF( m_useSurfaceConditions != 0 && m_useSurfaceConditions != 1, getWrapperDataContext( viewKeyStruct::useSurfaceConditionsString() ) << ": The flag to select surface/reservoir conditions must be equal to 0 or 1", InputError ); - // 4) check that at least one rate constraint has been defined -#if 0 - GEOS_THROW_IF( ((m_targetPhaseRate <= 0.0 && m_targetPhaseRateTableName.empty()) && - (m_targetMassRate <= 0.0 && m_targetMassRateTableName.empty()) && - (m_targetTotalRate <= 0.0 && m_targetTotalRateTableName.empty())), - "WellControls " << getDataContext() << ": You need to specify a phase, mass, or total rate constraint. \n" << - "The phase rate constraint can be specified using " << - "either " << viewKeyStruct::targetPhaseRateString() << - " or " << viewKeyStruct::targetPhaseRateTableNameString() << ".\n" << - "The total rate constraint can be specified using " << - "either " << viewKeyStruct::targetTotalRateString() << - " or " << viewKeyStruct::targetTotalRateTableNameString()<< - "The mass rate constraint can be specified using " << - "either " << viewKeyStruct::targetMassRateString() << - " or " << viewKeyStruct::targetMassRateTableNameString(), - InputError ); -#endif - // 5) check whether redundant information has been provided - GEOS_THROW_IF( ((m_targetPhaseRate > 0.0 && !m_targetPhaseRateTableName.empty())), - "WellControls " << getDataContext() << ": You have provided redundant information for well phase rate." << - " The keywords " << viewKeyStruct::targetPhaseRateString() << " and " << viewKeyStruct::targetPhaseRateTableNameString() << " cannot be specified together", - InputError ); - GEOS_THROW_IF( ((m_targetTotalRate > 0.0 && !m_targetTotalRateTableName.empty())), - "WellControls " << getDataContext() << ": You have provided redundant information for well total rate." << - " The keywords " << viewKeyStruct::targetTotalRateString() << " and " << viewKeyStruct::targetTotalRateTableNameString() << " cannot be specified together", - InputError ); - - GEOS_THROW_IF( ((m_targetBHP > 0.0 && !m_targetBHPTableName.empty())), - "WellControls " << getDataContext() << ": You have provided redundant information for well BHP." << - " The keywords " << viewKeyStruct::targetBHPString() << " and " << viewKeyStruct::targetBHPTableNameString() << " cannot be specified together", - InputError ); - - GEOS_THROW_IF( ((m_targetMassRate > 0.0 && !m_targetMassRateTableName.empty())), - "WellControls " << getDataContext() << ": You have provided redundant information for well mass rate." << - " The keywords " << viewKeyStruct::targetMassRateString() << " and " << viewKeyStruct::targetMassRateTableNameString() << " cannot be specified together", - InputError ); - - GEOS_THROW_IF( ((m_targetMassRate > 0.0 && m_useSurfaceConditions==0)), - "WellControls " << getDataContext() << ": Option only valid if useSurfaceConditions set to 1", - InputError ); + //GEOS_THROW_IF( ((m_targetMassRate > 0.0 && m_useSurfaceConditions==0)), + // "WellControls " << getDataContext() << ": Option only valid if useSurfaceConditions set to 1", + // InputError ); - GEOS_THROW_IF( ((m_useSurfaceConditions==1 && m_surfacePres< 0.0)), - "WellControls " << getDataContext() << " " << viewKeyStruct::surfacePressureString()<< " not set ", - InputError ); - GEOS_THROW_IF( ((m_useSurfaceConditions==1 && m_surfaceTemp<0.0)), - "WellControls " << getDataContext() << " " << viewKeyStruct::surfaceTemperatureString()<< " not set ", - InputError ); - - // 6.1) If the well is under BHP control then the BHP must be specified. - // Otherwise the BHP will be set to a default value. - if( m_currentControl == Control::BHP ) - { - GEOS_THROW_IF( ((m_targetBHP <= 0.0 && m_targetBHPTableName.empty())), - "WellControls " << getDataContext() << ": You have to provide well BHP by specifying either " - << viewKeyStruct::targetBHPString() << " or " << viewKeyStruct::targetBHPTableNameString(), - InputError ); - } - else if( m_targetBHP <= 0.0 && m_targetBHPTableName.empty() ) - { - m_targetBHP = isProducer() ? WellConstants::defaultProducerBHP : WellConstants::defaultInjectorBHP; - GEOS_LOG_LEVEL_RANK_0( logInfo::WellControl, - GEOS_FMT( "WellControls {}: Setting {} to default value {}", getDataContext(), viewKeyStruct::targetBHPString(), m_targetBHP )); - } - - // 6.2) Check incoherent information - - // An injector must be controlled by TotalVolRate - GEOS_THROW_IF( (isInjector() && (m_inputControl == Control::PHASEVOLRATE)), - "WellControls " << getDataContext() << ": You have to control an injector with " - << EnumStrings< Control >::toString( Control::TOTALVOLRATE ), - InputError ); - - // An injector must be controlled by TotalVolRate - GEOS_THROW_IF( (isProducer() && (m_inputControl == Control::MASSRATE)), - "WellControls " << getDataContext() << ": You have to control an injector with " - << EnumStrings< Control >::toString( Control::MASSRATE ), - InputError ); // 8) Make sure that the initial pressure coefficient is positive GEOS_THROW_IF( m_initialPressureCoefficient < 0, @@ -472,72 +234,7 @@ void WellControls::postInputInitialization() InputError ); - // 9) Create time-dependent BHP table - if( m_targetBHPTableName.empty() ) - { - m_targetBHPTableName = getName()+"_ConstantBHP_table"; - m_targetBHPTable = createWellTable( m_targetBHPTableName, m_targetBHP ); - } - else - { - FunctionManager & functionManager = FunctionManager::getInstance(); - m_targetBHPTable = &(functionManager.getGroup< TableFunction const >( m_targetBHPTableName )); - - GEOS_THROW_IF( m_targetBHPTable->getInterpolationMethod() != TableFunction::InterpolationType::Lower, - "WellControls " << getDataContext() << ": The interpolation method for the time-dependent BHP table " - << m_targetBHPTable->getName() << " should be TableFunction::InterpolationType::Lower", - InputError ); - } - - // 10) Create time-dependent total rate table - if( m_targetTotalRateTableName.empty() ) - { - m_targetTotalRateTableName = getName()+"_ConstantTotalRate_table"; - m_targetTotalRateTable = createWellTable( m_targetTotalRateTableName, m_targetTotalRate ); - } - else - { - FunctionManager & functionManager = FunctionManager::getInstance(); - m_targetTotalRateTable = &(functionManager.getGroup< TableFunction const >( m_targetTotalRateTableName )); - - GEOS_THROW_IF( m_targetTotalRateTable->getInterpolationMethod() != TableFunction::InterpolationType::Lower, - "WellControls " << getDataContext() << ": The interpolation method for the time-dependent total rate table " - << m_targetTotalRateTable->getName() << " should be TableFunction::InterpolationType::Lower", - InputError ); - } - - // 11) Create time-dependent phase rate table - if( m_targetPhaseRateTableName.empty() ) - { - m_targetPhaseRateTableName = getName()+"_ConstantPhaseRate_table"; - m_targetPhaseRateTable = createWellTable( m_targetPhaseRateTableName, m_targetPhaseRate ); - } - else - { - FunctionManager & functionManager = FunctionManager::getInstance(); - m_targetPhaseRateTable = &(functionManager.getGroup< TableFunction const >( m_targetPhaseRateTableName )); - GEOS_THROW_IF( m_targetPhaseRateTable->getInterpolationMethod() != TableFunction::InterpolationType::Lower, - "WellControls " << getDataContext() << ": The interpolation method for the time-dependent phase rate table " - << m_targetPhaseRateTable->getName() << " should be TableFunction::InterpolationType::Lower", - InputError ); - } - // Create time-dependent mass rate table - if( m_targetMassRateTableName.empty() ) - { - m_targetMassRateTableName = getName()+"_ConstantMassRate_table"; - m_targetMassRateTable = createWellTable( m_targetMassRateTableName, m_targetMassRate ); - } - else - { - FunctionManager & functionManager = FunctionManager::getInstance(); - m_targetMassRateTable = &(functionManager.getGroup< TableFunction const >( m_targetMassRateTableName )); - - GEOS_THROW_IF( m_targetMassRateTable->getInterpolationMethod() != TableFunction::InterpolationType::Lower, - "WellControls " << getDataContext() << ": The interpolation method for the time-dependent mass rate table " - << m_targetMassRateTable->getName() << " should be TableFunction::InterpolationType::Lower", - InputError ); - } // 12) Create the time-dependent well status table if( m_statusTableName.empty()) { @@ -609,11 +306,23 @@ bool WellControls::getConstraintSwitch() const void WellControls::setNextDtFromTables( real64 const & currentTime, real64 & nextDt ) { - // replace with iter over constraints - tjb - WellControls::setNextDtFromTable( m_targetBHPTable, currentTime, nextDt ); - WellControls::setNextDtFromTable( m_targetMassRateTable, currentTime, nextDt ); - WellControls::setNextDtFromTable( m_targetPhaseRateTable, currentTime, nextDt ); - WellControls::setNextDtFromTable( m_targetTotalRateTable, currentTime, nextDt ); + if( isProducer() ) + { + getMinBHPConstraint()->setNextDtFromTables( currentTime, nextDt ); + for( auto const & constraint : m_productionRateConstraintList ) + { + constraint->setNextDtFromTables( currentTime, nextDt ); + } + } + else + { + getMaxBHPConstraint()->setNextDtFromTables( currentTime, nextDt ); + for( auto const & constraint : m_injectionRateConstraintList ) + { + constraint->setNextDtFromTables( currentTime, nextDt ); + } + } + WellControls::setNextDtFromTable( m_statusTable, currentTime, nextDt ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp index c6553479894..082a57db8a4 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp @@ -147,29 +147,6 @@ class WellControls : public dataRepository::Group */ ///@{ - /** - * @brief Set the control type to BHP and set a numerical value for the control. - * @param[in] val value for the BHP control - */ - void switchToBHPControl( real64 const & val ); - - /** - * @brief Set the control type to total rate and set a numerical value for the control. - * @param[in] val value for the total volumetric rate - */ - void switchToTotalRateControl( real64 const & val ); - - /** - * @brief Set the control type to mass rate and set a numerical value for the control. - * @param[in] val value for the mass rate - */ - void switchToMassRateControl( real64 const & val ); - - /** - * @brief Set the control type to phase rate and set a numerical value for the control. - * @param[in] val value for the phase volumetric rate - */ - void switchToPhaseRateControl( real64 const & val ); /** * @brief Get the control type for the well. @@ -183,18 +160,6 @@ class WellControls : public dataRepository::Group */ void setControl( Control const & newControl ) { m_currentControl = newControl; } - /** - * @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 - */ - real64 getReferenceElevation() const { return m_refElevation; } - /** * @brief Getter for the reference gravity coefficient * @return the reference gravity coefficient @@ -208,59 +173,50 @@ class WellControls : public dataRepository::Group /** - * @brief Get the target bottom hole pressure value. - * @return a value for the target bottom hole pressure - */ - real64 getTargetBHP( real64 const & currentTime ) const - { - return m_targetBHPTable->evaluate( ¤tTime ); - } - - /** - * @brief Get the target total rate - * @return the target total rate + * @brief Returns the target bottom hole pressure value. + * @param[in] targetTime time at which to evaluate the constraint + * @return the injector maximum bottom hole pressure or producer minimum bottom hole pressure */ - real64 getTargetTotalRate( real64 const & currentTime ) const + real64 getTargetBHP( real64 const & targetTime ) const { - return m_rateSign * m_targetTotalRateTable->evaluate( ¤tTime ); + if( isProducer()) + { + return m_minBHPConstraint->getConstraintValue( targetTime ); + } + return m_maxBHPConstraint->getConstraintValue( targetTime ); } /** - * @brief Get the target phase rate - * @return the target phase rate + * @brief Const accessor for the temperature of the injection stream + * @return the temperature of the injection stream */ - real64 getTargetPhaseRate( real64 const & currentTime ) const + real64 getInjectionTemperature() const { - return m_rateSign * m_targetPhaseRateTable->evaluate( ¤tTime ); + real64 injectionTemperature = 0.0; + for( auto c : m_injectionRateConstraintList ) + if( c->isConstraintActive()) + { + injectionTemperature = dynamic_cast< InjectionConstraint * >(c)->getInjectionTemperature(); + break; + } + return injectionTemperature; } - /** - * @brief Get the target mass rate - * @return the target mass rate + * @brief Const accessor for the injection stream + * @return the injection stream */ - real64 getTargetMassRate( real64 const & currentTime ) const + arrayView1d< real64 const > getInjectionStream() const { - return m_rateSign * m_targetMassRateTable->evaluate( ¤tTime ); + arrayView1d< real64 const > injectionStream; + for( auto c : m_injectionRateConstraintList ) + if( c->isConstraintActive()) + { + injectionStream = dynamic_cast< InjectionConstraint * >(c)->getInjectionStream(); + break; + } + return injectionStream; } - /** - * @brief Get the target phase name - * @return the target phase name - */ - const string & getTargetPhaseName() const { return m_targetPhaseName; } - - /** - * @brief Const accessor for the composition of the injection stream - * @return a global component fraction vector - */ - arrayView1d< real64 const > getInjectionStream() const { return m_injectionStream; } - - /** - * @brief Const accessor for the temperature of the injection stream - * @return the temperature of the injection stream - */ - real64 getInjectionTemperature() const { return m_injectionTemperature; } - /** * @brief Getter for the flag specifying whether we check rates at surface or reservoir conditions * @return 1 if we use surface conditions, and 0 otherwise @@ -334,12 +290,6 @@ class WellControls : public dataRepository::Group */ void setNextDtFromTables( real64 const & currentTime, real64 & nextDt ); - /** - * @brief getter for esitmator switch - * @return True if estimate well solution - */ - integer estimateSolution() const { return m_estimateSolution; } - /** * @brief setter for multi fluid separator @@ -400,24 +350,10 @@ class WellControls : public dataRepository::Group static constexpr char const * refElevString() { return "referenceElevation"; } /// String key for the well type static constexpr char const * typeString() { return "type"; } - /// String key for the well input control - static constexpr char const * inputControlString() { return "control"; } + /// String key for the well current control static constexpr char const * currentControlString() { return "currentControl"; } - /// String key for the well target BHP - static constexpr char const * targetBHPString() { return "targetBHP"; } - /// String key for the well target rate - static constexpr char const * targetTotalRateString() { return "targetTotalRate"; } - /// String key for the well target phase rate - static constexpr char const * targetPhaseRateString() { return "targetPhaseRate"; } - /// String key for the well target phase name - static constexpr char const * targetPhaseNameString() { return "targetPhaseName"; } - /// String key for the well target phase name - static constexpr char const * targetMassRateString() { return "targetMassRate"; } - /// String key for the well injection stream - static constexpr char const * injectionStreamString() { return "injectionStream"; } - /// String key for the well injection temperature - static constexpr char const * injectionTemperatureString() { return "injectionTemperature"; } + /// String key for checking the rates at surface conditions static constexpr char const * useSurfaceConditionsString() { return "useSurfaceConditions"; } /// String key for reference reservoir region @@ -426,14 +362,7 @@ class WellControls : public dataRepository::Group static constexpr char const * surfacePressureString() { return "surfacePressure"; } /// String key for the surface temperature static constexpr char const * surfaceTemperatureString() { return "surfaceTemperature"; } - /// string key for total rate table name - static constexpr char const * targetTotalRateTableNameString() { return "targetTotalRateTableName"; } - /// string key for phase rate table name - static constexpr char const * targetPhaseRateTableNameString() { return "targetPhaseRateTableName"; } - /// string key for mass rate table name - static constexpr char const * targetMassRateTableNameString() { return "targetMassRateTableName"; } - /// string key for BHP table name - static constexpr char const * targetBHPTableNameString() { return "targetBHPTableName"; } + /// string key for status table name static constexpr char const * statusTableNameString() { return "statusTableName"; } /// string key for perforation status table name @@ -480,12 +409,15 @@ class WellControls : public dataRepository::Group /** * @brief Getters for constraints */ - std::shared_ptr< MinimumBHPConstraint > getMinBHPConstraint() { return m_minBHPConstraint; }; - std::shared_ptr< MaximumBHPConstraint > getMaxBHPConstraint() { return m_maxBHPConstraint; }; - + MinimumBHPConstraint * getMinBHPConstraint() { return m_minBHPConstraint; }; + MinimumBHPConstraint * getMinBHPConstraint() const { return m_minBHPConstraint; }; + MaximumBHPConstraint * getMaxBHPConstraint() { return m_maxBHPConstraint; }; + MaximumBHPConstraint * getMaxBHPConstraint() const { return m_maxBHPConstraint; }; // Lists of rate constraints - std::vector< std::shared_ptr< WellConstraintBase > > getProdRateConstraints() { return m_productionRateConstraintList; }; - std::vector< std::shared_ptr< WellConstraintBase > > getInjRateConstraints() { return m_injectionRateConstraintList; } + std::vector< WellConstraintBase * > getProdRateConstraints() { return m_productionRateConstraintList; }; + std::vector< WellConstraintBase * > getProdRateConstraints() const { return m_productionRateConstraintList; }; + std::vector< WellConstraintBase * > getInjRateConstraints() { return m_injectionRateConstraintList; } + std::vector< WellConstraintBase * > getInjRateConstraints() const { return m_injectionRateConstraintList; } protected: virtual void postInputInitialization() override; @@ -503,33 +435,9 @@ class WellControls : public dataRepository::Group /// Gravity coefficient of the reference elevation real64 m_refGravCoef; - /// Input well controls as a Control enum - Control m_inputControl; - /// Well controls as a Control enum Control m_currentControl; - /// Target bottom hole pressure value - real64 m_targetBHP; - - /// Target rate value - real64 m_targetTotalRate; - - /// Target phase rate value - real64 m_targetPhaseRate; - - /// Name of the targeted phase - string m_targetPhaseName; - - /// Target MassRate - real64 m_targetMassRate; - - /// Vector with global component fractions at the injector - array1d< real64 > m_injectionStream; - - /// Temperature at the injector - real64 m_injectionTemperature; - /// Flag to decide whether rates are controlled at rates or surface conditions integer m_useSurfaceConditions; @@ -545,17 +453,6 @@ class WellControls : public dataRepository::Group /// Surface temperature real64 m_surfaceTemp; - /// Total rate table name - string m_targetTotalRateTableName; - - /// Phase rate table name - string m_targetPhaseRateTableName; - - /// Mass rate table name - string m_targetMassRateTableName; - - /// BHP table name - string m_targetBHPTableName; /// Well status table name string m_statusTableName; @@ -572,25 +469,13 @@ class WellControls : public dataRepository::Group /// Rate sign. +1 for injector, -1 for producer real64 m_rateSign; - /// Total rate table - TableFunction const * m_targetTotalRateTable; - - /// Phase rate table - TableFunction const * m_targetPhaseRateTable; - - /// Mass rate table - TableFunction const * m_targetMassRateTable; - - /// BHP table - TableFunction const * m_targetBHPTable; /// Status table TableFunction const * m_statusTable; bool m_wellOpen; - /// flag to use the estimator - integer m_estimateSolution; + /// List of constraints //constraint_array m_ConstraintList; @@ -600,13 +485,13 @@ class WellControls : public dataRepository::Group // Current constraint WellConstraintBase * m_currentConstraint; // Minimum and maximum BHP and WHP constraints - std::shared_ptr< MinimumBHPConstraint > m_minBHPConstraint; - std::shared_ptr< MaximumBHPConstraint > m_maxBHPConstraint; + MinimumBHPConstraint * m_minBHPConstraint; + MaximumBHPConstraint * m_maxBHPConstraint; // Lists of rate constraints - std::vector< std::shared_ptr< WellConstraintBase > > m_productionRateConstraintList; - std::vector< std::shared_ptr< WellConstraintBase > > m_injectionRateConstraintList; + std::vector< WellConstraintBase * > m_productionRateConstraintList; + std::vector< WellConstraintBase * > m_injectionRateConstraintList; /// Well status diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.cpp index d52c494258b..83fb53b4658 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.cpp @@ -49,6 +49,19 @@ PhaseConstraint::PhaseConstraint( string const & name, Group * const parent ) setRestartFlags( RestartFlags::WRITE_AND_READ ). setDescription( "Name of the target phase" ); + if constexpr ( std::is_same_v< WellType, WellTypes::Injector > ) + { + registerWrapper( injectionStreamKey::injectionStreamString(), &m_injectionStream ). + setDefaultValue( -1 ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Global component densities of the injection stream [moles/m^3 or kg/m^3]" ); + + registerWrapper( injectionStreamKey::injectionTemperatureString(), &m_injectionTemperature ). + setDefaultValue( -1 ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Temperature of the injection stream [K]" ); + } } PhaseConstraint::~PhaseConstraint() @@ -121,6 +134,52 @@ bool PhaseInjectionConstraint::checkViolation( WellConstraintBase const & curren return currentConstraint.phaseVolumeRates()[m_phaseIndex] > getConstraintValue( currentTime ); } +template< typename WellConstraintType > +PhaseConstraint1< WellConstraintType >::PhaseConstraint1( string const & name, Group * const parent ) + : WellConstraintType( name, parent ) +{ + + setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); + + registerWrapper( viewKeyStruct::phaseRateString(), &m_constraintValue ). + setDefaultValue( 0.0 ). + setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). + setDescription( "Phase rate, (if useSurfaceConditions: [surface m^3/s]; else [reservoir m^3/s]) " ); + registerWrapper( viewKeyStruct::phaseNameString(), &m_phaseName ). + setRTTypeName( rtTypes::CustomTypes::groupNameRef ). + setDefaultValue( "" ). + setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). + setDescription( "Name of the target phase" ); +} + +PhaseConstraint1< WellConstraintType >::~PhaseConstraint1() +{} + +void PhaseConstraint1< WellConstraintType >::postInputInitialization() +{ + // Validate value and table options + WellConstraintType::postInputInitialization(); + +} + +bool PhaseConstraint1< WellConstraintType >::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const +{ + return currentConstraint.phaseVolumeRates()[m_phaseIndex] > getConstraintValue( currentTime ); +} + +namespace +{ +//typedef MultiphasePoromechanicsConformingFractures< MultiphaseReservoirAndWells<> > +// MultiphasePoromechanicsConformingFractures; +//REGISTER_CATALOG_ENTRY( PhysicsSolverBase, MultiphasePoromechanicsConformingFractures, string const &, Group * const ) +typedef PhaseConstraint1< InjectionConstraint > PhaseInjectionConstraint1; +REGISTER_CATALOG_ENTRY( WellConstraintBase, PhaseInjectionConstraint1, string const &, Group * const ) +typedef PhaseConstraint1< ProductionConstraint > PhaseProductionConstraint1; +REGISTER_CATALOG_ENTRY( WellConstraintBase, PhaseProductionConstraint1, string const &, Group * const ) + +} } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp index 55c881ad0a5..02fd0e0316b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp @@ -25,13 +25,14 @@ #include "dataRepository/Group.hpp" #include "functions/TableFunction.hpp" #include "WellConstraintsBase.hpp" +#include "WellConstants.hpp" namespace geos { template< typename T > -localIndex getPhaseIndex( T const & fluidModel, std::string const & inputPhase ) +localIndex getPhaseIndexFromFluidModel( T const & fluidModel, std::string const & inputPhase ) { localIndex phaseIndex=-1; // Find target phase index for phase rate constraint @@ -102,6 +103,8 @@ class PhaseConstraint : public WellConstraintBase ///@} + + /** * @name Getters / Setters */ @@ -116,6 +119,12 @@ class PhaseConstraint : public WellConstraintBase */ const string & getPhaseName() const { return m_phaseName; } + /** + * @brief Get the target phase index + * @return the target phase index + */ + const localIndex & getPhaseIndex() const { return m_phaseIndex; } + ///@} struct viewKeyStruct @@ -226,7 +235,7 @@ template< typename T > void PhaseProductionConstraint::validatePhaseType( T const & fluidModel ) { // Find target phase index for phase rate constraint - m_phaseIndex = getPhaseIndex( fluidModel, getReference< string >( PhaseConstraint::viewKeyStruct::phaseNameString())); + m_phaseIndex = getPhaseIndexFromFluidModel( fluidModel, getReference< string >( PhaseConstraint::viewKeyStruct::phaseNameString())); GEOS_THROW_IF( m_phaseIndex == -1, "PhaseProductionConstraint " << getReference< string >( PhaseConstraint::viewKeyStruct::phaseNameString()) << @@ -303,17 +312,6 @@ class PhaseInjectionConstraint : public PhaseConstraint virtual std::string getConstraintKey( ) const override { return "PhaseInjectionConstraint"; }; ///@} - /** - * @brief Struct to serve as a container for variable strings and keys. - * @struct viewKeyStruct - */ - struct injectionStreamKey - { - /// String key for the well injection stream - static constexpr char const * injectionStreamString() { return "injectionStream"; } - /// String key for the well injection temperature - static constexpr char const * injectionTemperatureString() { return "injectionTemperature"; } - }; /** * @brief Validate phase type is consistent with fluidmodel @@ -341,7 +339,7 @@ template< typename T > void PhaseInjectionConstraint::validatePhaseType( T const & fluidModel ) { // Find target phase index for phase rate constraint - m_phaseIndex = getPhaseIndex( fluidModel, getReference< string >( PhaseConstraint::viewKeyStruct::phaseNameString())); + m_phaseIndex = getPhaseIndexFromFluidModel( fluidModel, getReference< string >( PhaseConstraint::viewKeyStruct::phaseNameString())); GEOS_THROW_IF( m_phaseIndex == -1, "PhaseInjectionConstraint " << getReference< string >( PhaseConstraint::viewKeyStruct::phaseNameString()) << @@ -349,6 +347,142 @@ void PhaseInjectionConstraint::validatePhaseType( T const & fluidModel ) InputError ); } +/** + * @class PhaseInjectionConstraint + * @brief This class describes a phase rate constraint used to control a injection well. + */ +template< typename WellConstraintType > +class PhaseConstraint1 : public WellConstraintType +{ +public: + + + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for WellControls Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit PhaseConstraint1( string const & name, dataRepository::Group * const parent ); + + /** + * @brief Default destructor. + */ + ~PhaseConstraint1() override; + + /** + * @brief Deleted default constructor. + */ + PhaseConstraint1() = delete; + + /** + * @brief Deleted copy constructor. + */ + PhaseConstraint1( PhaseConstraint1 const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + PhaseConstraint1( PhaseConstraint1 && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + PhaseConstraint1 & operator=( PhaseConstraint1 const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + PhaseConstraint1 & operator=( PhaseConstraint1 && ) = delete; + + ///@} + + /** + * @brief name of the node manager in the object catalog + * @return string that contains the catalog name to generate a new MultiphasePoromechanics object through the object catalog. + */ + static string catalogName() + { + if constexpr ( std::is_same_v< WellConstraintType, InjectionConstraint > ) // special case + { + return "PhaseInjectionConstraint"; + } + else // default + { + return "PhaseProductionConstraint"; + } + } + + /** + * @name Getters / Setters + */ + ///@{ + + // Temp interface - tjb + virtual ConstraintTypeId getControl() const override { return ConstraintTypeId::PHASEVOLRATE; }; + + /** + * @brief Get the target phase name + * @return the target phase name + */ + const string & getPhaseName() const { return m_phaseName; } + + /** + * @brief Get the target phase index + * @return the target phase index + */ + const localIndex & getPhaseIndex() const { return m_phaseIndex; } + + ///@} + + struct viewKeyStruct + { + /// String key for the well target phase rate + static constexpr char const * phaseRateString() { return "phaseRate"; } + /// String key for the well target phase name + static constexpr char const * phaseNameString() { return "phaseName"; } + }; + + /** + * @brief Validate phase type is consistent with fluidmodel + */ + template< typename T > void validatePhaseType( T const & fluidModel ); + ///@} + + virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const override; +protected: + + virtual void postInputInitialization() override; + +private: + + /// Name of the targeted phase + string m_phaseName; + + /// Index of the target phase, used to impose the phase rate constraint + localIndex m_phaseIndex; + +}; + +template< typename WellConstraintType > +template< typename T > +void PhaseConstraint1< WellConstraintType >::validatePhaseType( T const & fluidModel ) +{ + // Find target phase index for phase rate constraint + m_phaseIndex = getPhaseIndexFromFluidModel( fluidModel, this->template getReference< string >( viewKeyStruct::phaseNameString())); + + GEOS_THROW_IF( m_phaseIndex == -1, + "PhaseConstraint " << this->template getReference< string >( viewKeyStruct::phaseNameString()) << + ": Invalid phase type for simulation fluid model", + InputError ); +} + } //namespace geos #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINT_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp index aee41ffafbf..35f7ecb1993 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp @@ -314,9 +314,9 @@ void WellSolverBase::selectWellConstraint( real64 const & time_n, DomainPartition & domain ) { GEOS_MARK_FUNCTION; - GEOS_UNUSED_VAR(dt); - GEOS_UNUSED_VAR(coupledIterationNumber); - + GEOS_UNUSED_VAR( dt ); + GEOS_UNUSED_VAR( coupledIterationNumber ); + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, MeshLevel & meshLevel, string_array const & regionNames ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.cpp index 86f974925d9..5094cdc761f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.cpp @@ -56,7 +56,6 @@ TotalVolProductionConstraint::TotalVolProductionConstraint( string const & name, : TotalVolConstraint( name, parent ) { setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); - m_rateSign=-1.0; } @@ -81,9 +80,6 @@ TotalVolInjectionConstraint::TotalVolInjectionConstraint( string const & name, G { setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); - - // Field registration - registerInjectionStream( m_injectionStream, m_injectionTemperature, *this ); } @@ -92,11 +88,7 @@ TotalVolInjectionConstraint::~TotalVolInjectionConstraint() void TotalVolInjectionConstraint::postInputInitialization() { - TotalVolConstraint::postInputInitialization(); -// Validate the injection stream and temperature - validateInjectionStream( m_injectionStream, m_injectionTemperature, getConstraintKey(), *this ); - } bool TotalVolInjectionConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime )const diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp index 0335333c898..03f902dbda2 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp @@ -301,11 +301,6 @@ void PressureRelationKernel:: launch( localIndex const size, globalIndex const rankOffset, - bool const isLocallyOwned, - localIndex const iwelemControl, - integer const targetPhaseIndex, - WellControls const & wellControls, - real64 const & time, arrayView1d< integer const > const elemStatus, arrayView1d< globalIndex const > const & wellElemDofNumber, arrayView1d< real64 const > const & wellElemGravCoef, @@ -318,43 +313,6 @@ PressureRelationKernel:: arrayView1d< real64 > const & localRhs ) { using COFFSET_WJ = compositionalMultiphaseWellKernels::ColOffset_WellJac< NC, IS_THERMAL >; - // static well control data - bool const isProducer = wellControls.isProducer(); - WellControls::Control const currentControl = wellControls.getControl(); - WellControls::Control const inputControl = wellControls.getInputControl(); - bool const constraintSwitch = wellControls.getConstraintSwitch(); - - real64 const targetBHP = wellControls.getTargetBHP( time ); - real64 const targetTotalRate = wellControls.getTargetTotalRate( time ); - real64 const targetPhaseRate = wellControls.getTargetPhaseRate( time ); - real64 const targetMassRate = wellControls.getTargetMassRate( time ); - - // temp tjb. only needed if new code path - real64 targetValue =0.0; - if( wellControls.getCurrentConstraint() != nullptr ) - targetValue = wellControls.getCurrentConstraint()->getConstraintValue( time ); - - // dynamic well control data - real64 const & currentBHP = - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() ); - arrayView1d< real64 const > const & dCurrentBHP = - wellControls.getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::dCurrentBHPString() ); - - arrayView1d< real64 const > const & currentPhaseVolRate = - wellControls.getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ); - arrayView2d< real64 const > const & dCurrentPhaseVolRate = - wellControls.getReference< array2d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::dCurrentPhaseVolRateString() ); - - real64 const & currentTotalVolRate = - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() ); - 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() ); RAJA::ReduceMax< parallelDeviceReduce, localIndex > switchControl( 0 ); @@ -368,61 +326,7 @@ PressureRelationKernel:: localIndex const iwelemNext = nextWellElemIndex[iwelem]; - if( iwelemNext < 0 && isLocallyOwned ) // if iwelemNext < 0, form control equation - { - - WellControls::Control newControl = currentControl; - if( false && constraintSwitch ) - { - - ControlEquationHelper::selectLimitingConstraint( isProducer, - inputControl, - currentControl, - targetPhaseIndex, - targetBHP, - targetPhaseRate, - targetTotalRate, - targetMassRate, - currentBHP, - currentPhaseVolRate, - currentTotalVolRate, - currentMassRate, - newControl ); - } - else - { - newControl = currentControl; - } - - if( currentControl != newControl ) - { - switchControl.max( 1 ); - } - if( constraintSwitch ) - { - ControlEquationHelper::compute< NC, IS_THERMAL >( rankOffset, - newControl, - targetPhaseIndex, // tjb - remove ? - targetBHP, // tjb - remove - targetPhaseRate, // tjb - remove - targetTotalRate, // tjb - remove - targetMassRate, // tjb - remove - targetValue, // tjb - currentBHP, - dCurrentBHP, - currentPhaseVolRate, - dCurrentPhaseVolRate, - currentTotalVolRate, - dCurrentTotalVolRate, - massDensity, - wellElemDofNumber[iwelemControl], - localMatrix, - localRhs ); - } - // TODO: for consistency, we should assemble here, not in compute... - - } - else if( iwelemNext >= 0 ) // if iwelemNext >= 0, form momentum equation + if( iwelemNext >= 0 ) // if iwelemNext >= 0, form momentum equation { real64 localPresRel = 0; @@ -476,11 +380,6 @@ PressureRelationKernel:: void PressureRelationKernel:: \ launch< NC, IS_THERMAL >( localIndex const size, \ globalIndex const rankOffset, \ - bool const isLocallyOwned, \ - localIndex const iwelemControl, \ - integer const targetPhaseIndex, \ - WellControls const & wellControls, \ - real64 const & time, \ arrayView1d< integer const > const elemStatus, \ arrayView1d< globalIndex const > const & wellElemDofNumber, \ arrayView1d< real64 const > const & wellElemGravCoef, \ @@ -737,62 +636,74 @@ CompDensInitializationKernel:: void RateInitializationKernel:: launch( localIndex const subRegionSize, - integer const targetPhaseIndex, WellControls const & wellControls, real64 const & time, arrayView3d< real64 const, multifluid::USD_PHASE > const & phaseDens, arrayView2d< real64 const, multifluid::USD_FLUID > const & totalDens, arrayView1d< real64 > const & connRate ) { - WellControls::Control const control = wellControls.getControl(); - bool const isProducer = wellControls.isProducer(); - real64 const targetTotalRate = wellControls.getTargetTotalRate( time ); - real64 const targetPhaseRate = wellControls.getTargetPhaseRate( time ); - real64 const targetMassRate = wellControls.getTargetMassRate( time ); - - // Estimate the connection rates - forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) + if( wellControls.isProducer() ) { - if( control == WellControls::Control::BHP ) + std::vector< WellConstraintBase * > const constraints = wellControls.getProdRateConstraints(); + // Use first rate constraint to set initial connection rates + real64 const constraintVal = constraints[0]->getConstraintValue( time ); + ConstraintTypeId const controlType = constraints[0]->getControl(); + if( controlType == ConstraintTypeId::PHASEVOLRATE ) { - // if BHP constraint set rate below the absolute max rate - // with the appropriate sign (negative for prod, positive for inj) - if( isProducer ) + integer const targetPhaseIndex = dynamic_cast< const PhaseConstraint1< ProductionConstraint > * >( constraints[0] )->getPhaseIndex(); + + forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) { - connRate[iwelem] = LvArray::math::max( 0.1 * targetPhaseRate * phaseDens[iwelem][0][targetPhaseIndex], -1e3 ); - } - else + connRate[iwelem] = LvArray::math::max( 0.1 * constraintVal * phaseDens[iwelem][0][targetPhaseIndex], -1e3 ); + } ); + } + else if( controlType == ConstraintTypeId::TOTALVOLRATE ) + { + forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) { - if( isZero( targetMassRate ) ) - { - connRate[iwelem] = LvArray::math::min( 0.1 * targetTotalRate * totalDens[iwelem][0], 1e3 ); - } - else - { - connRate[iwelem] = targetMassRate; - } - - } + connRate[iwelem] = LvArray::math::max( 0.1 * constraintVal * totalDens[iwelem][0], -1e3 ); + } ); } - else if( control == WellControls::Control::MASSRATE ) + else if( controlType == ConstraintTypeId::MASSRATE ) { - connRate[iwelem] = targetMassRate; + forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) + { + connRate[iwelem] = constraintVal; + } ); } - else + } + else + { + std::vector< WellConstraintBase * > const constraints = wellControls.getInjRateConstraints(); + // Use first rate constraint to set initial connection rates + real64 const constraintVal = constraints[0]->getConstraintValue( time ); + ConstraintTypeId const controlType = constraints[0]->getControl(); + if( controlType == ConstraintTypeId::PHASEVOLRATE ) { - if( isProducer ) + integer const targetPhaseIndex = dynamic_cast< const PhaseConstraint1< InjectionConstraint > * >( constraints[0] )->getPhaseIndex(); + + forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) { - connRate[iwelem] = targetPhaseRate * phaseDens[iwelem][0][targetPhaseIndex]; - } - else + connRate[iwelem] = LvArray::math::max( 0.1 * constraintVal * phaseDens[iwelem][0][targetPhaseIndex], 1e3 ); + } ); + } + else if( controlType == ConstraintTypeId::TOTALVOLRATE ) + { + forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) { - connRate[iwelem] = targetTotalRate * totalDens[iwelem][0]; - } + connRate[iwelem] = LvArray::math::max( 0.1 * constraintVal * totalDens[iwelem][0], 1e3 ); + } ); } - } ); + else if( controlType == ConstraintTypeId::MASSRATE ) + { + forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) + { + connRate[iwelem] = constraintVal; + } ); + } + } } - } // end namespace compositionalMultiphaseWellKernels } // end namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp index 32826be15e3..bf60e40ffe9 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp @@ -40,6 +40,7 @@ #include "physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWellFields.hpp" #include "physicsSolvers/fluidFlow/wells/WellControls.hpp" #include "physicsSolvers/fluidFlow/wells/WellSolverBaseFields.hpp" +#include "physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp" namespace geos { @@ -201,11 +202,6 @@ struct PressureRelationKernel static void launch( localIndex const size, globalIndex const rankOffset, - bool const isLocallyOwned, - localIndex const iwelemControl, - integer const targetPhaseIndex, - WellControls const & wellControls, - real64 const & time, arrayView1d< integer const > const elemStatus, arrayView1d< globalIndex const > const & wellElemDofNumber, arrayView1d< real64 const > const & wellElemGravCoef, @@ -324,7 +320,6 @@ struct RateInitializationKernel static void launch( localIndex const subRegionSize, - integer const targetPhaseIndex, WellControls const & wellControls, real64 const & currentTime, arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const & phaseDens, @@ -506,7 +501,6 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa arrayView1d< localIndex const > const & ghostRank, integer const numComp, integer const numDof, - integer const targetPhaseIndex, WellElementSubRegion const & subRegion, constitutive::MultiFluidBase const & fluid, WellControls const & wellControls, @@ -520,20 +514,35 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa minNormalizer ), m_numComp( numComp ), m_numDof( numDof ), - m_targetPhaseIndex( targetPhaseIndex ), m_dt( dt ), m_isLocallyOwned( subRegion.isLocallyOwned() ), m_iwelemControl( subRegion.getTopWellElementIndex() ), m_isProducer( wellControls.isProducer() ), m_currentControl( wellControls.getControl() ), - m_targetBHP( wellControls.getTargetBHP( time ) ), - m_targetTotalRate( wellControls.getTargetTotalRate( time ) ), - m_targetPhaseRate( wellControls.getTargetPhaseRate( time ) ), - m_targetMassRate( wellControls.getTargetMassRate( time ) ), + m_constraintValue ( wellControls.getCurrentConstraint()->getConstraintValue( time )), m_volume( subRegion.getElementVolume() ), m_phaseDens_n( fluid.phaseDensity_n() ), m_totalDens_n( fluid.totalDensity_n() ) - {} + { + if( m_isProducer ) + { + m_targetBHP = wellControls.getMinBHPConstraint()->getConstraintValue( time ); + if( m_currentControl == WellControls::Control::PHASEVOLRATE ) + { + m_targetPhaseIndex = dynamic_cast< const PhaseConstraint1< ProductionConstraint > * >( wellControls.getCurrentConstraint() )->getPhaseIndex(); + } + } + else + { + m_targetBHP = wellControls.getMaxBHPConstraint()->getConstraintValue( time ); + if( m_currentControl == WellControls::Control::PHASEVOLRATE ) + { + m_targetPhaseIndex = dynamic_cast< const PhaseConstraint1< InjectionConstraint > * >( wellControls.getCurrentConstraint() )->getPhaseIndex(); + } + } + + + } GEOS_HOST_DEVICE virtual void computeLinf( localIndex const iwelem, @@ -562,17 +571,17 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa else if( m_currentControl == WellControls::Control::TOTALVOLRATE ) { // the residual entry is in volume / time units - normalizer = LvArray::math::max( LvArray::math::abs( m_targetTotalRate ), m_minNormalizer ); + normalizer = LvArray::math::max( LvArray::math::abs( m_constraintValue ), m_minNormalizer ); } else if( m_currentControl == WellControls::Control::PHASEVOLRATE ) { // the residual entry is in volume / time units - normalizer = LvArray::math::max( LvArray::math::abs( m_targetPhaseRate ), m_minNormalizer ); + normalizer = LvArray::math::max( LvArray::math::abs( m_constraintValue ), m_minNormalizer ); } else if( m_currentControl == WellControls::Control::MASSRATE ) { // the residual entry is in volume / time units - normalizer = LvArray::math::max( LvArray::math::abs( m_targetMassRate ), m_minNormalizer ); + normalizer = LvArray::math::max( LvArray::math::abs( m_constraintValue ), m_minNormalizer ); } } // for the pressure difference equation, always normalize by the BHP @@ -587,18 +596,18 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa if( m_isProducer ) // only PHASEVOLRATE is supported for now { // the residual is in mass units - normalizer = m_dt * LvArray::math::abs( m_targetPhaseRate ) * m_phaseDens_n[iwelem][0][m_targetPhaseIndex]; + normalizer = m_dt * LvArray::math::abs( m_constraintValue ) * m_phaseDens_n[iwelem][0][m_targetPhaseIndex]; } else // Type::INJECTOR, only TOTALVOLRATE is supported for now { if( m_currentControl == WellControls::Control::MASSRATE ) { - normalizer = m_dt * LvArray::math::abs( m_targetMassRate ); + normalizer = m_dt * LvArray::math::abs( m_constraintValue ); } else { // the residual is in mass units - normalizer = m_dt * LvArray::math::abs( m_targetTotalRate ) * m_totalDens_n[iwelem][0]; + normalizer = m_dt * LvArray::math::abs( m_constraintValue ) * m_totalDens_n[iwelem][0]; } } @@ -612,17 +621,17 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa if( m_isProducer ) // only PHASEVOLRATE is supported for now { // the residual is in volume units - normalizer = m_dt * LvArray::math::abs( m_targetPhaseRate ); + normalizer = m_dt * LvArray::math::abs( m_constraintValue ); } else // Type::INJECTOR, only TOTALVOLRATE is supported for now { if( m_currentControl == WellControls::Control::MASSRATE ) { - normalizer = m_dt * LvArray::math::abs( m_targetMassRate/ m_totalDens_n[iwelem][0] ); + normalizer = m_dt * LvArray::math::abs( m_constraintValue/ m_totalDens_n[iwelem][0] ); } else { - normalizer = m_dt * LvArray::math::abs( m_targetTotalRate ); + normalizer = m_dt * LvArray::math::abs( m_constraintValue ); } } @@ -659,7 +668,7 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa integer const m_numDof; /// Index of the target phase - integer const m_targetPhaseIndex; + integer m_targetPhaseIndex; /// Time step size real64 const m_dt; @@ -675,10 +684,9 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa /// Controls WellControls::Control const m_currentControl; - real64 const m_targetBHP; - real64 const m_targetTotalRate; - real64 const m_targetPhaseRate; - real64 const m_targetMassRate; + real64 const m_constraintValue; + real64 m_targetBHP; + /// View on the volume arrayView1d< real64 const > const m_volume; @@ -701,7 +709,6 @@ class ResidualNormKernelFactory * @tparam POLICY the policy used in the RAJA kernel * @param[in] numComp number of fluid components * @param[in] numDof number of dofs per well element - * @param[in] targetPhaseIndex the index of the target phase (for phase volume control) * @param[in] rankOffset the offset of my MPI rank * @param[in] dofKey the string key to retrieve the degress of freedom numbers * @param[in] localResidual the residual vector on my MPI rank @@ -716,7 +723,6 @@ class ResidualNormKernelFactory static void createAndLaunch( integer const numComp, integer const numDof, - integer const targetPhaseIndex, globalIndex const rankOffset, string const & dofKey, arrayView1d< real64 const > const & localResidual, @@ -732,7 +738,7 @@ class ResidualNormKernelFactory arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); ResidualNormKernel kernel( rankOffset, localResidual, dofNumber, ghostRank, - numComp, numDof, targetPhaseIndex, subRegion, fluid, wellControls, time, dt, minNormalizer ); + numComp, numDof, subRegion, fluid, wellControls, time, dt, minNormalizer ); ResidualNormKernel::launchLinf< POLICY >( subRegion.size(), kernel, residualNorm ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp index 54b7819e8bf..f27176b4872 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp @@ -22,6 +22,8 @@ #include "physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp" #include "physicsSolvers/PhysicsSolverBaseKernels.hpp" +#include "physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp" +#include "physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp" namespace geos { @@ -161,7 +163,7 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa arrayView1d< real64 const > const & localResidual, arrayView1d< globalIndex const > const & dofNumber, arrayView1d< localIndex const > const & ghostRank, - integer const targetPhaseIndex, + WellElementSubRegion const & subRegion, MultiFluidBase const & fluid, WellControls const & wellControls, @@ -174,22 +176,31 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa ghostRank, minNormalizer ), m_numPhases( fluid.numFluidPhases()), - m_targetPhaseIndex( targetPhaseIndex ), m_dt( dt ), m_isLocallyOwned( subRegion.isLocallyOwned() ), m_iwelemControl( subRegion.getTopWellElementIndex() ), m_isProducer( wellControls.isProducer() ), m_currentControl( wellControls.getControl() ), - m_targetBHP( wellControls.getTargetBHP( time ) ), - m_targetTotalRate( wellControls.getTargetTotalRate( time ) ), - m_targetPhaseRate( wellControls.getTargetPhaseRate( time ) ), - m_targetMassRate( wellControls.getTargetMassRate( time ) ), + m_constraintValue ( wellControls.getCurrentConstraint()->getConstraintValue( time )), m_volume( subRegion.getElementVolume() ), m_phaseDens_n( fluid.phaseDensity_n() ), m_totalDens_n( fluid.totalDensity_n() ), m_phaseVolFraction_n( subRegion.getField< fields::well::phaseVolumeFraction_n >()), m_phaseInternalEnergy_n( fluid.phaseInternalEnergy_n() ) - {} + { + if( m_isProducer ) + { + m_targetBHP = wellControls.getMinBHPConstraint()->getConstraintValue( time ); + } + else + { + m_targetBHP = wellControls.getMaxBHPConstraint()->getConstraintValue( time ); + } + if( m_currentControl == WellControls::Control::PHASEVOLRATE ) + { + m_targetPhaseIndex = dynamic_cast< const PhaseConstraint * >( wellControls.getCurrentConstraint() )->getPhaseIndex(); + } + } GEOS_HOST_DEVICE @@ -232,17 +243,17 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa else if( m_currentControl == WellControls::Control::TOTALVOLRATE ) { // the residual entry is in volume / time units - normalizer = LvArray::math::max( LvArray::math::abs( m_targetTotalRate ), m_minNormalizer ); + normalizer = LvArray::math::max( LvArray::math::abs( m_constraintValue ), m_minNormalizer ); } else if( m_currentControl == WellControls::Control::PHASEVOLRATE ) { // the residual entry is in volume / time units - normalizer = LvArray::math::max( LvArray::math::abs( m_targetPhaseRate ), m_minNormalizer ); + normalizer = LvArray::math::max( LvArray::math::abs( m_constraintValue ), m_minNormalizer ); } else if( m_currentControl == WellControls::Control::MASSRATE ) { // the residual entry is in volume / time units - normalizer = LvArray::math::max( LvArray::math::abs( m_targetMassRate ), m_minNormalizer ); + normalizer = LvArray::math::max( LvArray::math::abs( m_constraintValue ), m_minNormalizer ); } } // for the pressure difference equation, always normalize by the BHP @@ -257,18 +268,18 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa if( m_isProducer ) // only PHASEVOLRATE is supported for now { // the residual is in mass units - normalizer = m_dt * LvArray::math::abs( m_targetPhaseRate ) * m_phaseDens_n[iwelem][0][m_targetPhaseIndex]; + normalizer = m_dt * LvArray::math::abs( m_constraintValue ) * m_phaseDens_n[iwelem][0][m_targetPhaseIndex]; } else // Type::INJECTOR, only TOTALVOLRATE is supported for now { if( m_currentControl == WellControls::Control::MASSRATE ) { - normalizer = m_dt * LvArray::math::abs( m_targetMassRate ); + normalizer = m_dt * LvArray::math::abs( m_constraintValue ); } else { // the residual is in mass units - normalizer = m_dt * LvArray::math::abs( m_targetTotalRate ) * m_totalDens_n[iwelem][0]; + normalizer = m_dt * LvArray::math::abs( m_constraintValue ) * m_totalDens_n[iwelem][0]; } } @@ -282,17 +293,17 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa if( m_isProducer ) // only PHASEVOLRATE is supported for now { // the residual is in volume units - normalizer = m_dt * LvArray::math::abs( m_targetPhaseRate ); + normalizer = m_dt * LvArray::math::abs( m_constraintValue ); } else // Type::INJECTOR, only TOTALVOLRATE is supported for now { if( m_currentControl == WellControls::Control::MASSRATE ) { - normalizer = m_dt * LvArray::math::abs( m_targetMassRate/ m_totalDens_n[iwelem][0] ); + normalizer = m_dt * LvArray::math::abs( m_constraintValue/ m_totalDens_n[iwelem][0] ); } else { - normalizer = m_dt * LvArray::math::abs( m_targetTotalRate ); + normalizer = m_dt * LvArray::math::abs( m_constraintValue ); } } @@ -339,7 +350,7 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa integer const m_numPhases; /// Index of the target phase - integer const m_targetPhaseIndex; + integer m_targetPhaseIndex; /// Time step size real64 const m_dt; @@ -355,10 +366,9 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa /// Controls WellControls::Control const m_currentControl; - real64 const m_targetBHP; - real64 const m_targetTotalRate; - real64 const m_targetPhaseRate; - real64 const m_targetMassRate; + real64 const m_constraintValue; + real64 m_targetBHP; + /// View on the volume arrayView1d< real64 const > const m_volume; @@ -383,7 +393,6 @@ class ResidualNormKernelFactory * @tparam POLICY the policy used in the RAJA kernel * @param[in] numComp number of fluid components * @param[in] numDof number of dofs per well element - * @param[in] targetPhaseIndex the index of the target phase (for phase volume control) * @param[in] rankOffset the offset of my MPI rank * @param[in] dofKey the string key to retrieve the degress of freedom numbers * @param[in] localResidual the residual vector on my MPI rank @@ -397,7 +406,6 @@ class ResidualNormKernelFactory template< typename POLICY > static void createAndLaunch( integer const numComp, - integer const targetPhaseIndex, globalIndex const rankOffset, string const & dofKey, arrayView1d< real64 const > const & localResidual, @@ -418,7 +426,7 @@ class ResidualNormKernelFactory arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); kernelType kernel( rankOffset, localResidual, dofNumber, ghostRank, - targetPhaseIndex, subRegion, fluid, wellControls, time, dt, minNormalizer ); + subRegion, fluid, wellControls, time, dt, minNormalizer ); kernelType::template launchLinf< POLICY >( subRegion.size(), kernel, residualNorm ); } ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/WellConstraintKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/WellConstraintKernels.hpp index 250fca30455..a99691e8d68 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/WellConstraintKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/WellConstraintKernels.hpp @@ -158,7 +158,7 @@ struct ConstraintHelper< NC, IS_THERMAL, PhaseConstraint > arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > const & dPhaseDens = fluidSeparator.dPhaseDensity(); // constraint data - integer ip = getPhaseIndex( fluidSeparator, constraint.getPhaseName()); + integer ip = getPhaseIndexFromFluidModel( fluidSeparator, constraint.getPhaseName()); real64 const & targetPhaseRate = constraint.getConstraintValue( time_n ); // current constraint value From 8366922fbed242debce054c87a9dcb02e69e8407 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 7 Oct 2025 12:01:32 -0700 Subject: [PATCH 06/71] 1) SinglePhaseWell adopts new constraint convention, 2) Change constraint class hierachy , 3) Remove all old constraint handling methods/variables, 4) it compiles ... --- .../physicsSolvers/fluidFlow/CMakeLists.txt | 2 +- .../wells/CompositionalMultiphaseWell.cpp | 65 +- .../fluidFlow/wells/SinglePhaseWell.cpp | 713 +++++++++++++----- .../fluidFlow/wells/SinglePhaseWell.hpp | 70 ++ .../fluidFlow/wells/WellBHPConstraints.hpp | 26 +- .../fluidFlow/wells/WellConstraintsBase.cpp | 25 +- .../fluidFlow/wells/WellConstraintsBase.hpp | 51 +- .../fluidFlow/wells/WellControls.cpp | 45 +- .../fluidFlow/wells/WellControls.hpp | 22 +- .../wells/WellLiquidRateConstraints.cpp | 48 +- .../wells/WellLiquidRateConstraints.hpp | 131 +--- .../wells/WellMassRateConstraints.cpp | 81 +- .../wells/WellMassRateConstraints.hpp | 186 +---- .../wells/WellPhaseRateConstraints.cpp | 140 +--- .../wells/WellPhaseRateConstraints.hpp | 311 +------- .../fluidFlow/wells/WellSolverBase.hpp | 89 ++- .../wells/WellTotalVolRateConstraints.cpp | 67 +- .../wells/WellTotalVolRateConstraints.hpp | 191 +---- .../CompositionalMultiphaseWellKernels.cpp | 4 +- .../CompositionalMultiphaseWellKernels.hpp | 4 +- .../SinglePhaseWellConstraintKernels.hpp | 196 +++++ .../wells/kernels/SinglePhaseWellKernels.cpp | 81 +- .../wells/kernels/SinglePhaseWellKernels.hpp | 33 +- ...rmalCompositionalMultiphaseWellKernels.hpp | 13 +- .../kernels/ThermalSinglePhaseWellKernels.hpp | 26 +- .../wells/kernels/WellConstraintKernels.hpp | 39 +- 26 files changed, 1174 insertions(+), 1485 deletions(-) create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellConstraintKernels.hpp diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt index 11818d57fc8..cba20d05b19 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt +++ b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt @@ -128,7 +128,7 @@ set( fluidFlowSolvers_headers wells/kernels/SinglePhaseWellKernels.hpp wells/kernels/CompositionalMultiphaseWellKernels.hpp wells/kernels/WellConstraintKernels.hpp - + wells/kernels/SinglePhaseWellConstraintKernels.hpp proppantTransport/ProppantTransport.hpp proppantTransport/ProppantTransportFields.hpp proppantTransport/ProppantTransportKernels.hpp ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index cf3c3f7ab3c..758df943552 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -404,7 +404,7 @@ void CompositionalMultiphaseWell::validateWellConstraints( real64 const & time_n WellElementSubRegion const & subRegion, ElementRegionManager const & elemManager ) { - GEOS_UNUSED_VAR(time_n); + GEOS_UNUSED_VAR( time_n ); WellControls & wellControls = getWellControls( subRegion ); if( !wellControls.useSurfaceConditions() ) { @@ -445,7 +445,7 @@ void CompositionalMultiphaseWell::validateWellConstraints( real64 const & time_n MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); // tjb - wellControls.forSubGroups< PhaseProductionConstraint, PhaseInjectionConstraint >( [&]( auto & constraint ) + wellControls.forSubGroups< PhaseConstraint< InjectionConstraint >, PhaseConstraint< ProductionConstraint > >( [&]( auto & constraint ) { constraint.validatePhaseType( fluid ); } ); @@ -1355,7 +1355,7 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh { // tjb needed for backward compatibility //wellControls.forSubGroups< MaximumBHPConstraint >( [&]( auto & constraint ) - wellControls.forSubGroups< TotalVolInjectionConstraint >( [&]( auto & constraint ) + wellControls.forSubGroups< TotalVolConstraint< InjectionConstraint > >( [&]( auto & constraint ) { constraint.setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); constraint.setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( @@ -2638,41 +2638,40 @@ void CompositionalMultiphaseWell::assembleWellConstraintTerms( real64 const & ti } WellControls & wellControls = getWellControls( subRegion ); + + wellControls.forSubGroups< MinimumBHPConstraint, PhaseConstraint< ProductionConstraint >, MassConstraint< ProductionConstraint >, TotalVolConstraint< ProductionConstraint >, + LiquidConstraint< ProductionConstraint >, MaximumBHPConstraint, PhaseConstraint< InjectionConstraint >, MassConstraint< InjectionConstraint >, + TotalVolConstraint< InjectionConstraint >, + LiquidConstraint< InjectionConstraint > + >( [&]( auto & constraint ) { - wellControls.forSubGroups< BHPConstraint, PhaseConstraint, MassConstraint, TotalVolConstraint, LiquidConstraint >( [&]( auto & constraint ) + if( constraint.getName() == wellControls.getCurrentConstraint()->getName()) { - using ConstraintType = std::remove_reference_t< decltype(constraint) >; - if( constraint.getName() == wellControls.getCurrentConstraint()->getName()) - { - // found limiting constraint - - // fluid data - constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); - integer isThermal = fluidSeparator.isThermal(); - integer const numComp = fluidSeparator.numFluidComponents(); - geos::internal::kernelLaunchSelectorCompThermSwitch( numComp, isThermal, [&] ( auto NC, auto ISTHERMAL ) - { - integer constexpr NUM_COMP = NC(); - integer constexpr IS_THERMAL = ISTHERMAL(); - - wellConstraintKernels::ConstraintHelper< NUM_COMP, IS_THERMAL, ConstraintType >::assembleConstraintEquation( time_n, - wellControls, - constraint, - subRegion, - dofManager.getKey( wellElementDofName() ), - dofManager.rankOffset(), - localMatrix, - localRhs ); - } ); - } - - } ); - } + // found limiting constraint + // fluid data + constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); + integer isThermal = fluidSeparator.isThermal(); + integer const numComp = fluidSeparator.numFluidComponents(); + geos::internal::kernelLaunchSelectorCompThermSwitch( numComp, isThermal, [&] ( auto NC, auto ISTHERMAL ) + { + integer constexpr NUM_COMP = NC(); + integer constexpr IS_THERMAL = ISTHERMAL(); + + wellConstraintKernels::ConstraintHelper< NUM_COMP, IS_THERMAL >::assembleConstraintEquation( time_n, + wellControls, + constraint, + subRegion, + dofManager.getKey( wellElementDofName() ), + dofManager.rankOffset(), + localMatrix, + localRhs ); + } ); + } + } ); } - -void CompositionalMultiphaseWell::assembleWellPressureRelations( real64 const & GEOS_UNUSED_PARAM(time_n), +void CompositionalMultiphaseWell::assembleWellPressureRelations( real64 const & GEOS_UNUSED_PARAM( time_n ), real64 const & GEOS_UNUSED_PARAM( dt ), WellElementSubRegion const & subRegion, DofManager const & dofManager, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index 4dd455afeb1..7d5b80c6058 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -44,7 +44,7 @@ #include "physicsSolvers/fluidFlow/kernels/singlePhase/FluidUpdateKernel.hpp" #include "physicsSolvers/fluidFlow/kernels/singlePhase/SolutionCheckKernel.hpp" #include "physicsSolvers/fluidFlow/SinglePhaseStatistics.hpp" - +#include "physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellConstraintKernels.hpp" namespace geos { @@ -143,6 +143,7 @@ void SinglePhaseWell::validateWellConstraints( real64 const & time_n, WellElementSubRegion const & subRegion, ElementRegionManager const & elemManager ) { + GEOS_UNUSED_VAR( time_n ); // tjb this will be needed with validation against tables WellControls & wellControls = getWellControls( subRegion ); if( !wellControls.useSurfaceConditions() ) { @@ -176,7 +177,9 @@ void SinglePhaseWell::validateWellConstraints( real64 const & time_n, wellControls.setRegionAverageTemperature( stats.averageTemperature ); } } + #if 0 // tjb vix this WellControls::Control currentControl = wellControls.getControl(); + real64 const targetTotalRate = wellControls.getTargetTotalRate( time_n ); real64 const targetPhaseRate = wellControls.getTargetPhaseRate( time_n ); GEOS_THROW_IF( currentControl == WellControls::Control::PHASEVOLRATE, @@ -193,6 +196,7 @@ void SinglePhaseWell::validateWellConstraints( real64 const & time_n, "WellControls " << wellControls.getDataContext() << ": Target phase rate cannot be used for SinglePhaseWell", InputError ); +#endif } void SinglePhaseWell::updateBHPForConstraint( WellElementSubRegion & subRegion ) @@ -420,9 +424,78 @@ real64 SinglePhaseWell::updateSubRegionState( WellElementSubRegion & subRegion ) void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) { GEOS_UNUSED_VAR( domain ); - GEOS_UNUSED_VAR( mesh ); - GEOS_UNUSED_VAR( subRegion ); - GEOS_UNUSED_VAR( time_n ); + WellControls const & wellControls = getWellControls( subRegion ); + PerforationData const & perforationData = *subRegion.getPerforationData(); + + // get the info stored on well elements + arrayView1d< real64 const > const wellElemGravCoef = + subRegion.getField< well::gravityCoefficient >(); + + // get well primary variables on well elements + arrayView1d< real64 > const wellElemPressure = + subRegion.getField< well::pressure >(); + arrayView1d< real64 > const connRate = + subRegion.getField< well::connectionRate >(); + arrayView1d< real64 > const wellElemTemperature = + subRegion.getField< well::temperature >(); + // get the element region, subregion, index + arrayView1d< localIndex const > const resElementRegion = + perforationData.getField< perforation::reservoirElementRegion >(); + arrayView1d< localIndex const > const resElementSubRegion = + perforationData.getField< perforation::reservoirElementSubRegion >(); + arrayView1d< localIndex const > const resElementIndex = + perforationData.getField< perforation::reservoirElementIndex >(); + + arrayView1d< real64 const > const & perfGravCoef = + perforationData.getField< well::gravityCoefficient >(); + + bool const hasNonZeroRate = MpiWrapper::max< integer >( hasNonZero( connRate )); + + if( time_n <= 0.0 || (wellControls.isWellOpen() && !hasNonZeroRate ) ) + { + // TODO: change the way we access the flowSolver here + SinglePhaseBase const & flowSolver = getParent().getGroup< SinglePhaseBase >( getFlowSolverName() ); + PresTempInitializationKernel::SinglePhaseFlowAccessors resSinglePhaseFlowAccessors( mesh.getElemManager(), flowSolver.getName() ); + PresTempInitializationKernel::SingleFluidAccessors resSingleFluidAccessors( mesh.getElemManager(), flowSolver.getName() ); + + // 1) Loop over all perforations to compute an average density + // 2) Initialize the reference pressure + // 3) Estimate the pressures in the well elements using the average density + PresTempInitializationKernel:: + launch( isThermal(), + perforationData.size(), + subRegion.size(), + perforationData.getNumPerforationsGlobal(), + wellControls, + 0.0, // initialization done at t = 0 + resSinglePhaseFlowAccessors.get( flow::pressure{} ), + resSinglePhaseFlowAccessors.get( flow::temperature{} ), + resSingleFluidAccessors.get( fields::singlefluid::density{} ), + resElementRegion, + resElementSubRegion, + resElementIndex, + perfGravCoef, + wellElemGravCoef, + wellElemPressure, + wellElemTemperature ); + + // 4) Recompute the pressure-dependent properties + // Note: I am leaving that here because I would like to use the perforationRates (computed in UpdateState) + // to better initialize the rates + updateSubRegionState( subRegion ); + + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + SingleFluidBase & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); + arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > const & wellElemDens = fluid.density(); + + // 5) Estimate the well rates + RateInitializationKernel::launch( subRegion.size(), + wellControls, + 0.0, // initialization done at t = 0 + wellElemDens, + connRate ); + } + }; void SinglePhaseWell::initializeWells( DomainPartition & domain, real64 const & time_n ) { @@ -431,87 +504,16 @@ void SinglePhaseWell::initializeWells( DomainPartition & domain, real64 const & // loop over the wells forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & meshLevel, + MeshLevel & mesh, string_array const & regionNames ) { - ElementRegionManager & elemManager = meshLevel.getElemManager(); + ElementRegionManager & elemManager = mesh.getElemManager(); elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, WellElementSubRegion & subRegion ) { - WellControls const & wellControls = getWellControls( subRegion ); - PerforationData const & perforationData = *subRegion.getPerforationData(); - - // get the info stored on well elements - arrayView1d< real64 const > const wellElemGravCoef = - subRegion.getField< well::gravityCoefficient >(); - - // get well primary variables on well elements - arrayView1d< real64 > const wellElemPressure = - subRegion.getField< well::pressure >(); - arrayView1d< real64 > const connRate = - subRegion.getField< well::connectionRate >(); - arrayView1d< real64 > const wellElemTemperature = - subRegion.getField< well::temperature >(); - // get the element region, subregion, index - arrayView1d< localIndex const > const resElementRegion = - perforationData.getField< perforation::reservoirElementRegion >(); - arrayView1d< localIndex const > const resElementSubRegion = - perforationData.getField< perforation::reservoirElementSubRegion >(); - arrayView1d< localIndex const > const resElementIndex = - perforationData.getField< perforation::reservoirElementIndex >(); - - arrayView1d< real64 const > const & perfGravCoef = - perforationData.getField< well::gravityCoefficient >(); - - bool const hasNonZeroRate = MpiWrapper::max< integer >( hasNonZero( connRate )); - - if( wellControls.isWellOpen() && !hasNonZeroRate ) - { - // TODO: change the way we access the flowSolver here - SinglePhaseBase const & flowSolver = getParent().getGroup< SinglePhaseBase >( getFlowSolverName() ); - PresTempInitializationKernel::SinglePhaseFlowAccessors resSinglePhaseFlowAccessors( meshLevel.getElemManager(), flowSolver.getName() ); - PresTempInitializationKernel::SingleFluidAccessors resSingleFluidAccessors( meshLevel.getElemManager(), flowSolver.getName() ); - - // 1) Loop over all perforations to compute an average density - // 2) Initialize the reference pressure - // 3) Estimate the pressures in the well elements using the average density - PresTempInitializationKernel:: - launch( isThermal(), - perforationData.size(), - subRegion.size(), - perforationData.getNumPerforationsGlobal(), - wellControls, - 0.0, // initialization done at t = 0 - resSinglePhaseFlowAccessors.get( flow::pressure{} ), - resSinglePhaseFlowAccessors.get( flow::temperature{} ), - resSingleFluidAccessors.get( fields::singlefluid::density{} ), - resElementRegion, - resElementSubRegion, - resElementIndex, - perfGravCoef, - wellElemGravCoef, - wellElemPressure, - wellElemTemperature ); - - // 4) Recompute the pressure-dependent properties - // Note: I am leaving that here because I would like to use the perforationRates (computed in UpdateState) - // to better initialize the rates - updateSubRegionState( subRegion ); - - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - SingleFluidBase & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); - arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > const & wellElemDens = fluid.density(); - - // 5) Estimate the well rates - RateInitializationKernel::launch( subRegion.size(), - wellControls, - 0.0, // initialization done at t = 0 - wellElemDens, - connRate ); - } - + initializeWell( domain, mesh, subRegion, time_n ); } ); } ); @@ -592,6 +594,33 @@ void SinglePhaseWell::shutDownWell( real64 const time_n, } ); } +real64 SinglePhaseWell::updateWellState( WellElementSubRegion & subRegion ) +{ + GEOS_MARK_FUNCTION; + + updateSubRegionState( subRegion ); + return 0.0; +} +void SinglePhaseWell::updateState( DomainPartition & domain ) +{ + GEOS_MARK_FUNCTION; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + WellControls & wellControls = getWellControls( subRegion ); + if( wellControls.getWellState()) + { + updateWellState( subRegion ); + } + } ); + } ); + +} void SinglePhaseWell::assembleSystem( real64 const time, real64 const dt, DomainPartition & domain, @@ -618,6 +647,48 @@ void SinglePhaseWell::assembleSystem( real64 const time, shutDownWell( time, domain, dofManager, localMatrix, localRhs ); } +void SinglePhaseWell::assembleWellFluxTerms( real64 const & time, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + GEOS_MARK_FUNCTION; + GEOS_UNUSED_VAR( time ); + WellControls const & wellControls = getWellControls( subRegion ); + // get a reference to the degree-of-freedom numbers + string const wellDofKey = dofManager.getKey( wellElementDofName() ); + + if( isThermal() ) + { + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + SingleFluidBase const & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); + thermalSinglePhaseWellKernels:: + FaceBasedAssemblyKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( dt, + dofManager.rankOffset(), + wellDofKey, + wellControls, + subRegion, + fluid, + localMatrix, + localRhs ); + } + else + { + singlePhaseWellKernels:: + FaceBasedAssemblyKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( dt, + dofManager.rankOffset(), + wellDofKey, + wellControls, + subRegion, + localMatrix, + localRhs ); + } + +} void SinglePhaseWell::assembleFluxTerms( real64 const & time_n, real64 const & dt, DomainPartition & domain, @@ -626,8 +697,6 @@ void SinglePhaseWell::assembleFluxTerms( real64 const & time_n, arrayView1d< real64 > const & localRhs ) { GEOS_MARK_FUNCTION; - GEOS_UNUSED_VAR( time_n ); - GEOS_UNUSED_VAR( dt ); // loop over the wells forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, @@ -642,45 +711,106 @@ void SinglePhaseWell::assembleFluxTerms( real64 const & time_n, WellElementSubRegion const & subRegion ) { - WellControls const & wellControls = getWellControls( subRegion ); - // get a reference to the degree-of-freedom numbers - string const wellDofKey = dofManager.getKey( wellElementDofName() ); + assembleWellFluxTerms( time_n, dt, subRegion, dofManager, localMatrix, localRhs ); + } ); - if( isThermal() ) - { - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - SingleFluidBase const & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); - thermalSinglePhaseWellKernels:: - FaceBasedAssemblyKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( dt, - dofManager.rankOffset(), - wellDofKey, - wellControls, - subRegion, - fluid, - localMatrix, - localRhs ); - } - else + } ); +} + + +void SinglePhaseWell::assembleWellConstraintTerms( real64 const & time_n, + real64 const & GEOS_UNUSED_PARAM( dt ), + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + GEOS_MARK_FUNCTION; + + + // the rank that owns the reference well element is responsible for the calculations below. + if( !subRegion.isLocallyOwned() ) + { + return; + } + WellControls & wellControls = getWellControls( subRegion ); + + { + // tjb wellControls.forSubGroups< BHPConstraint, MassConstraint, TotalVolConstraint >( [&]( auto & constraint ) + wellControls.forSubGroups< BHPConstraint, TotalVolConstraint< InjectionConstraint >, TotalVolConstraint< ProductionConstraint > >( [&]( auto & constraint ) + { + if( constraint.getName() == wellControls.getCurrentConstraint()->getName()) { - singlePhaseWellKernels:: - FaceBasedAssemblyKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( dt, - dofManager.rankOffset(), - wellDofKey, - wellControls, - subRegion, - localMatrix, - localRhs ); + // found limiting constraint + + // fluid data + constitutive::SingleFluidBase & fluidSeparator = wellControls.getSingleFluidSeparator(); + integer isThermal = fluidSeparator.isThermal(); + + geos::internal::kernelLaunchSelectorThermalSwitch( isThermal, [&] ( auto ISTHERMAL ) + { + integer constexpr IS_THERMAL = ISTHERMAL(); + + singlePhaseWellConstraintKernels::ConstraintHelper< IS_THERMAL >::assembleConstraintEquation( time_n, + wellControls, + constraint, + subRegion, + dofManager.getKey( wellElementDofName() ), + dofManager.rankOffset(), + localMatrix, + localRhs ); + } ); } } ); + } - } ); } +void SinglePhaseWell::assembleWellPressureRelations( real64 const & GEOS_UNUSED_PARAM( time_n ), + real64 const & GEOS_UNUSED_PARAM( dt ), + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + + // get the degrees of freedom numbers, depth, next well elem index + string const wellDofKey = dofManager.getKey( wellElementDofName() ); + arrayView1d< globalIndex const > const & wellElemDofNumber = + subRegion.getReference< array1d< globalIndex > >( wellDofKey ); + arrayView1d< real64 const > const & wellElemGravCoef = + subRegion.getField< well::gravityCoefficient >(); + arrayView1d< localIndex const > const & nextWellElemIndex = + subRegion.getReference< array1d< localIndex > >( WellElementSubRegion::viewKeyStruct::nextWellElementIndexString() ); + + // get primary variables on well elements + arrayView1d< real64 const > const & wellElemPressure = + subRegion.getField< well::pressure >(); + + // get well constitutive data + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + SingleFluidBase const & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); + arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > const & wellElemDensity = fluid.density(); + arrayView3d< real64 const, constitutive::singlefluid::USD_FLUID_DER > const & dWellElemDensity = fluid.dDensity(); + + geos::internal::kernelLaunchSelectorThermalSwitch( isThermal(), [&] ( auto ISTHERMAL ) + { + PressureRelationKernel::launch< ISTHERMAL >( subRegion.size(), + dofManager.rankOffset(), + wellElemDofNumber, + wellElemGravCoef, + nextWellElemIndex, + wellElemPressure, + wellElemDensity, + dWellElemDensity, + localMatrix, + localRhs ); + } ); + +} void SinglePhaseWell::assemblePressureRelations( real64 const & time_n, - real64 const & GEOS_UNUSED_PARAM( dt ), + real64 const & dt, DomainPartition const & domain, DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, @@ -701,68 +831,53 @@ void SinglePhaseWell::assemblePressureRelations( real64 const & time_n, WellElementSubRegion const & subRegion ) { - WellControls & wellControls = getWellControls( subRegion ); - - // get the degrees of freedom numbers, depth, next well elem index - string const wellDofKey = dofManager.getKey( wellElementDofName() ); - arrayView1d< globalIndex const > const & wellElemDofNumber = - subRegion.getReference< array1d< globalIndex > >( wellDofKey ); - arrayView1d< real64 const > const & wellElemGravCoef = - subRegion.getField< well::gravityCoefficient >(); - arrayView1d< localIndex const > const & nextWellElemIndex = - subRegion.getReference< array1d< localIndex > >( WellElementSubRegion::viewKeyStruct::nextWellElementIndexString() ); + assembleWellPressureRelations( time_n, dt, subRegion, dofManager, localMatrix, localRhs ); + } ); + } ); +} +void SinglePhaseWell::assembleWellAccumulationTerms( real64 const & time, + real64 const & dt, + WellElementSubRegion & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) - // get primary variables on well elements - arrayView1d< real64 const > const & wellElemPressure = - subRegion.getField< well::pressure >(); +{ + GEOS_UNUSED_VAR( time ); + GEOS_UNUSED_VAR( dt ); + // get a reference to the degree-of-freedom numbers + string const wellElemDofKey = dofManager.getKey( wellElementDofName() ); - // get well constitutive data - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - SingleFluidBase const & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); - arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > const & wellElemDensity = fluid.density(); - arrayView3d< real64 const, constitutive::singlefluid::USD_FLUID_DER > const & dWellElemDensity = fluid.dDensity(); + WellControls const & wellControls = getWellControls( subRegion ); + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + SingleFluidBase const & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); - geos::internal::kernelLaunchSelectorThermalSwitch( isThermal(), [&] ( auto ISTHERMAL ) - { - localIndex controlHasSwitched=0; - controlHasSwitched = PressureRelationKernel::launch< ISTHERMAL >( subRegion.size(), - dofManager.rankOffset(), - subRegion.isLocallyOwned(), - subRegion.getTopWellElementIndex(), - wellControls, - time_n, - wellElemDofNumber, - wellElemGravCoef, - nextWellElemIndex, - wellElemPressure, - wellElemDensity, - dWellElemDensity, - localMatrix, - localRhs ); - - if( controlHasSwitched == 1 ) - { - // Note: if BHP control is not viable, we switch to TOTALVOLRATE - // if TOTALVOLRATE is not viable, we switch to BHP + if( isThermal() ) + { + thermalSinglePhaseWellKernels:: + ElementBasedAssemblyKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( wellControls.isProducer(), + dofManager.rankOffset(), + wellElemDofKey, + subRegion, + fluid, + localMatrix, + localRhs ); + } + else + { + singlePhaseWellKernels:: + ElementBasedAssemblyKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( dofManager.rankOffset(), + wellElemDofKey, + subRegion, + fluid, + localMatrix, + localRhs ); + } +} - if( wellControls.getControl() == WellControls::Control::BHP ) - { - wellControls.switchToTotalRateControl( wellControls.getTargetTotalRate( time_n ) ); - GEOS_LOG_LEVEL_RANK_0( logInfo::WellControl, - GEOS_FMT( "Control switch for well {} from BHP constraint to rate constraint", subRegion.getName()) ); - } - else - { - wellControls.switchToBHPControl( wellControls.getTargetBHP( time_n ) ); - GEOS_LOG_LEVEL_RANK_0( logInfo::WellControl, - GEOS_FMT( "Control switch for well {} from rate constraint to BHP constraint", subRegion.getName()) ); - } - } - } ); - } ); - } ); -} void SinglePhaseWell::assembleAccumulationTerms( real64 const & time_n, real64 const & dt, @@ -772,54 +887,22 @@ void SinglePhaseWell::assembleAccumulationTerms( real64 const & time_n, arrayView1d< real64 > const & localRhs ) { GEOS_MARK_FUNCTION; - GEOS_UNUSED_VAR( time_n ); - GEOS_UNUSED_VAR( dt ); + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel const & mesh, + MeshLevel & mesh, string_array const & regionNames ) { - ElementRegionManager const & elemManager = mesh.getElemManager(); + ElementRegionManager & elemManager = mesh.getElemManager(); elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, - WellElementSubRegion const & subRegion ) + WellElementSubRegion & subRegion ) { - - // get a reference to the degree-of-freedom numbers - string const wellElemDofKey = dofManager.getKey( wellElementDofName() ); - - WellControls const & wellControls = getWellControls( subRegion ); - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - SingleFluidBase const & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); - - if( isThermal() ) - { - thermalSinglePhaseWellKernels:: - ElementBasedAssemblyKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( wellControls.isProducer(), - dofManager.rankOffset(), - wellElemDofKey, - subRegion, - fluid, - localMatrix, - localRhs ); - } - else - { - singlePhaseWellKernels:: - ElementBasedAssemblyKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( dofManager.rankOffset(), - wellElemDofKey, - subRegion, - fluid, - localMatrix, - localRhs ); - } + assembleWellAccumulationTerms( time_n, dt, subRegion, dofManager, localMatrix, localRhs ); } ); } ); - // then assemble the volume balance equations - assembleVolumeBalanceTerms( domain, dofManager, localMatrix, localRhs ); + } void SinglePhaseWell::assembleVolumeBalanceTerms( DomainPartition const & GEOS_UNUSED_PARAM( domain ), @@ -894,6 +977,123 @@ void SinglePhaseWell::computePerforationRates( real64 const & time_n, } +real64 +SinglePhaseWell::calculateWellResidualNorm( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs ) +{ + GEOS_MARK_FUNCTION; + integer numNorm = 1; // mass balance + array1d< real64 > localResidualNorm; + array1d< real64 > localResidualNormalizer; + + if( isThermal() ) + { + numNorm = 2; // mass balance and energy balance + } + localResidualNorm.resize( numNorm ); + localResidualNormalizer.resize( numNorm ); + + + globalIndex const rankOffset = dofManager.rankOffset(); + string const wellDofKey = dofManager.getKey( wellElementDofName() ); + + + + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + SingleFluidBase const & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); + + WellControls const & wellControls = getWellControls( subRegion ); + + // step 1: compute the norm in the subRegion + if( isThermal() ) + { + real64 subRegionResidualNorm[2]{}; + thermalSinglePhaseWellKernels::ResidualNormKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( rankOffset, + wellDofKey, + localRhs, + subRegion, + fluid, + wellControls, + time_n, + dt, + m_nonlinearSolverParameters.m_minNormalizer, + subRegionResidualNorm ); + // step 2: reduction across meshBodies/regions/subRegions + + for( integer i=0; i localResidualNorm[i] ) + { + localResidualNorm[i] = subRegionResidualNorm[i]; + } + } + } + else + { + real64 subRegionResidualNorm[1]{}; + ResidualNormKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( rankOffset, + wellDofKey, + localRhs, + subRegion, + fluid, + wellControls, + time_n, + dt, + m_nonlinearSolverParameters.m_minNormalizer, + subRegionResidualNorm ); + + // step 2: reduction across meshBodies/regions/subRegions + + if( subRegionResidualNorm[0] > localResidualNorm[0] ) + { + localResidualNorm[0] = subRegionResidualNorm[0]; + } + } + + + real64 resNorm=localResidualNorm[0]; + if( isThermal() ) + { + real64 globalResidualNorm[2]{}; + globalResidualNorm[0] = MpiWrapper::max( localResidualNorm[0] ); + globalResidualNorm[1] = MpiWrapper::max( localResidualNorm[1] ); + resNorm= std::sqrt( globalResidualNorm[0] * globalResidualNorm[0] + globalResidualNorm[1] * globalResidualNorm[1] ); + + GEOS_LOG_LEVEL_RANK_0_NLR( logInfo::ResidualNorm, GEOS_FMT( " ( R{} ) = ( {:4.2e} ) ( Renergy ) = ( {:4.2e} )", + coupledSolverAttributePrefix(), globalResidualNorm[0], globalResidualNorm[1] )); + + getConvergenceStats().setResidualValue( GEOS_FMT( "R{}", coupledSolverAttributePrefix()), globalResidualNorm[0] ); + getConvergenceStats().setResidualValue( "Renergy", globalResidualNorm[1] ); + } + else + { + resNorm = MpiWrapper::max( resNorm ); + + GEOS_LOG_LEVEL_RANK_0_NLR( logInfo::ResidualNorm, GEOS_FMT( " ( R{} ) = ( {:4.2e} )", + coupledSolverAttributePrefix(), resNorm )); + getConvergenceStats().setResidualValue( GEOS_FMT( "R{}", coupledSolverAttributePrefix()), resNorm ); + } + + return resNorm; +} +real64 +SinglePhaseWell::scalingForWellSystemSolution( ElementSubRegionBase & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution ) +{ + GEOS_MARK_FUNCTION; + GEOS_UNUSED_VAR( subRegion ); + GEOS_UNUSED_VAR( dofManager ); + GEOS_UNUSED_VAR( localSolution ); + + return 1.0; +} + real64 SinglePhaseWell::calculateResidualNorm( real64 const & time_n, real64 const & dt, @@ -1010,6 +1210,47 @@ SinglePhaseWell::calculateResidualNorm( real64 const & time_n, return resNorm; } +bool SinglePhaseWell::checkWellSystemSolution( ElementSubRegionBase & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor ) +{ + GEOS_MARK_FUNCTION; + + string const wellDofKey = dofManager.getKey( wellElementDofName() ); + integer numNegativePressures = 0; + real64 minPressure = 0.0; + + + globalIndex const rankOffset = dofManager.rankOffset(); + // get the degree of freedom numbers on well elements + arrayView1d< globalIndex const > const & dofNumber = + subRegion.getReference< array1d< globalIndex > >( wellDofKey ); + arrayView1d< integer const > const & ghostRank = subRegion.ghostRank(); + + // get a reference to the primary variables on well elements + arrayView1d< real64 const > const & pres = + subRegion.getField< well::pressure >(); + + auto const statistics = + singlePhaseBaseKernels::SolutionCheckKernel:: + launch< parallelDevicePolicy<> >( localSolution, rankOffset, dofNumber, ghostRank, pres, scalingFactor ); + + numNegativePressures += statistics.first; + minPressure = std::min( minPressure, statistics.second ); + + + numNegativePressures = MpiWrapper::sum( numNegativePressures ); + + if( numNegativePressures > 0 ) + { + GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, + GEOS_FMT( " {}: Number of negative pressure values: {}, minimum value: {} Pa", + getName(), numNegativePressures, fmt::format( "{:.{}f}", minPressure, 3 ) ) ); + } + + return (m_allowNegativePressure || numNegativePressures == 0) ? 1 : 0; +} bool SinglePhaseWell::checkSystemSolution( DomainPartition & domain, DofManager const & dofManager, @@ -1044,7 +1285,7 @@ bool SinglePhaseWell::checkSystemSolution( DomainPartition & domain, arrayView1d< real64 const > const & pres = subRegion.getField< well::pressure >(); - auto const statistics = + std::pair< integer, real64 > statistics = singlePhaseBaseKernels::SolutionCheckKernel:: launch< parallelDevicePolicy<> >( localSolution, rankOffset, dofNumber, ghostRank, pres, scalingFactor ); @@ -1065,6 +1306,66 @@ bool SinglePhaseWell::checkSystemSolution( DomainPartition & domain, return (m_allowNegativePressure || numNegativePressures == 0) ? 1 : 0; } +void +SinglePhaseWell::applyWellSystemSolution( DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor, + real64 const dt, + DomainPartition & domain, + MeshLevel & mesh, + WellElementSubRegion & subRegion ) +{ + GEOS_UNUSED_VAR( dt ); + GEOS_UNUSED_VAR( subRegion ); + DofManager::CompMask pressureMask( m_numDofPerWellElement, 0, 1 ); + DofManager::CompMask connRateMask( m_numDofPerWellElement, 1, 2 ); + dofManager.addVectorToField( localSolution, + wellElementDofName(), + well::pressure::key(), + scalingFactor, + pressureMask ); + + dofManager.addVectorToField( localSolution, + wellElementDofName(), + well::connectionRate::key(), + scalingFactor, + connRateMask ); + + if( isThermal() ) + { + DofManager::CompMask temperatureMask( m_numDofPerWellElement, 2, 3 ); + + dofManager.addVectorToField( localSolution, + wellElementDofName(), + fields::well::temperature::key(), + scalingFactor, + temperatureMask ); + + } + + + FieldIdentifiers fieldsToBeSync; + if( isThermal() ) + { + fieldsToBeSync.addElementFields( { well::pressure::key(), + well::connectionRate::key(), + well::temperature::key() }, + getTargetRegionNames() ); + } + else + { + fieldsToBeSync.addElementFields( { well::pressure::key(), + well::connectionRate::key() }, + getTargetRegionNames() ); + } + CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, + mesh, + domain.getNeighbors(), + true ); + + +} + void SinglePhaseWell::applySystemSolution( DofManager const & dofManager, arrayView1d< real64 const > const & localSolution, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp index efd03cd276c..c66cb83e6a1 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp @@ -95,6 +95,15 @@ class SinglePhaseWell : public WellSolverBase */ /**@{*/ + virtual real64 scalingForWellSystemSolution( ElementSubRegionBase & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution ) override; + virtual real64 + calculateWellResidualNorm( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs ) override; virtual real64 calculateResidualNorm( real64 const & time_n, real64 const & dt, @@ -102,6 +111,12 @@ class SinglePhaseWell : public WellSolverBase DofManager const & dofManager, arrayView1d< real64 const > const & localRhs ) override; + virtual bool + checkWellSystemSolution( ElementSubRegionBase & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor ) override; + virtual bool checkSystemSolution( DomainPartition & domain, DofManager const & dofManager, @@ -109,6 +124,14 @@ class SinglePhaseWell : public WellSolverBase real64 const scalingFactor ) override; virtual void + applyWellSystemSolution( DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor, + real64 const dt, + DomainPartition & domain, + MeshLevel & mesh, + WellElementSubRegion & subRegion ) override; + virtual void applySystemSolution( DofManager const & dofManager, arrayView1d< real64 const > const & localSolution, real64 const scalingFactor, @@ -163,6 +186,14 @@ class SinglePhaseWell : public WellSolverBase virtual void computePerforationRates( real64 const & time_n, real64 const & dt, DomainPartition & domain ) override; + /** + * @brief Recompute all dependent quantities from primary variables (including constitutive + * models) + * @param domain the domain containing the mesh and fields + */ + virtual real64 updateWellState( WellElementSubRegion & subRegion ) override; + virtual void updateState( DomainPartition & domain ) override; + /** * @brief Recompute all dependent quantities from primary variables (including constitutive models) on the well * @param subRegion the well subRegion containing the well elements and their associated fields @@ -185,6 +216,21 @@ class SinglePhaseWell : public WellSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) override; + /** + * @brief assembles the flux terms for all connections between well elements + * @param time_n previous time value + * @param dt time step + * @param domain the physical domain object + * @param dofManager degree-of-freedom manager associated with the linear system + * @param matrix the system matrix + * @param rhs the system right-hand side vector + */ + virtual void assembleWellFluxTerms( real64 const & time, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; /** * @brief assembles the flux terms for all connections between well elements * @param time_n previous time value @@ -208,6 +254,14 @@ class SinglePhaseWell : public WellSolverBase * @param matrix the system matrix * @param rhs the system right-hand side vector */ + + virtual void assembleWellAccumulationTerms( real64 const & time, + real64 const & dt, + WellElementSubRegion & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; + virtual void assembleAccumulationTerms( real64 const & time_n, real64 const & dt, DomainPartition & domain, DofManager const & dofManager, @@ -226,6 +280,22 @@ class SinglePhaseWell : public WellSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ); + virtual void assembleWellConstraintTerms( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; + + + virtual void assembleWellPressureRelations( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; + + /** * @brief assembles the pressure relations at all connections between well elements except at the well head * @param time_n time at the beginning of the time step diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp index 09c80d17c36..1ca0a53da24 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp @@ -92,17 +92,6 @@ class BHPConstraint : public WellConstraintBase // Temp interface - tjb virtual ConstraintTypeId getControl() const override { return ConstraintTypeId::BHP; }; - /** - * @name Getters / Setters - */ - ///@{ - /** - * @brief Get name of constraint - * @return constraint key - */ - virtual std::string getConstraintKey( ) const override { return "BHPConstraint"; }; - ///@} - ///@} /** * @brief Struct to serve as a container for variable strings and keys. @@ -215,14 +204,7 @@ class MinimumBHPConstraint : public BHPConstraint */ ///@{ - // Temp interface - tjb - virtual ConstraintTypeId getControl() const override { return ConstraintTypeId::BHP; }; - /** - * @brief Get name of constraint - * @return constraint key - */ - virtual std::string getConstraintKey( ) const override { return "MinimumBHPConstraint"; }; - ///@} + /** * @brief Struct to serve as a container for variable strings and keys. * @struct viewKeyStruct @@ -305,11 +287,7 @@ class MaximumBHPConstraint : public BHPConstraint ///@{ // Temp interface - tjb virtual ConstraintTypeId getControl() const override { return ConstraintTypeId::BHP; }; - /** - * @brief Get name of constraint - * @return constraint key - */ - virtual std::string getConstraintKey( ) const override { return "MaximumBHPConstraint"; }; + ///@} /** diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp index 626b486c436..f3bbfc1e129 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp @@ -29,6 +29,16 @@ namespace geos using namespace dataRepository; +// Provide a properly-typed static catalog for WellConstraintBase so that +// CatalogInterface< WellConstraintBase, ... >::getCatalog() can return +// a catalog of CatalogInterface objects instead of +// inheriting Group::getCatalog() which returns a catalog of Group entries. +WellConstraintBase::CatalogInterface::CatalogType & WellConstraintBase::getCatalog() +{ + static WellConstraintBase::CatalogInterface::CatalogType catalog; + return catalog; +} + namespace { @@ -89,7 +99,7 @@ void WellConstraintBase::postInputInitialization() GEOS_THROW_IF( ((m_constraintValue > 0.0 && !m_constraintScheduleTableName.empty())), - getConstraintKey() << " " << getDataContext() << ": You have provided redundant information for well constraint value ." << + getName() << " " << getDataContext() << ": You have provided redundant information for well constraint value ." << " A constraint value and table of constraint values cannot be specified together", InputError ); @@ -100,14 +110,14 @@ void WellConstraintBase::postInputInitialization() m_constraintScheduleTable = &(functionManager.getGroup< TableFunction const >( m_constraintScheduleTableName )); GEOS_THROW_IF( m_constraintScheduleTable->getInterpolationMethod() != TableFunction::InterpolationType::Lower, - getConstraintKey() << " " << getDataContext() << ": The interpolation method for the schedule table " - << m_constraintScheduleTable->getName() << " should be TableFunction::InterpolationType::Lower", + getName() << " " << getDataContext() << ": The interpolation method for the schedule table " + << m_constraintScheduleTable->getName() << " should be TableFunction::InterpolationType::Lower", InputError ); } GEOS_THROW_IF ((m_constraintValue <= 0.0 && m_constraintScheduleTableName.empty()), - getConstraintKey() << " " << getDataContext() << ": You need to specify a volume rate constraint. \n" << + getName() << " " << getDataContext() << ": You need to specify a volume rate constraint. \n" << "The rate constraint can be specified using " << "either " << constraintViewStruct::constraintValueKey::constraintValueString() << " or " << constraintViewStruct::constraintValueKey::constraintScheduleTableNameString(), @@ -180,6 +190,13 @@ void InjectionConstraint::postInputInitialization() void InjectionConstraint::validateInjectionStream( ) { + GEOS_THROW_IF( (m_injectionStream.empty() && m_injectionTemperature >= 0) || + (!m_injectionStream.empty() && m_injectionTemperature < 0), + getName() << " " << getDataContext() << ": Both " + << constraintViewStruct::injectionStreamKey::injectionStreamString() << " and " << injectionStreamKey::injectionTemperatureString() + << " must be specified for multiphase simulations", + InputError ); + if( !m_injectionStream.empty()) { real64 sum = 0.0; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp index 781ee973f07..373acbdd72c 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp @@ -133,40 +133,6 @@ void validateSurfaceConditions( integer useSurfaceConditions, } -/** - * @brief Validate the injection stream and temperature. - * @param[in] injectionStream the injection stream vector - * @param[in] injectionTemperature the injection temperature - * @param[in] dataContext context for error messages - */ -template< typename T > -void validateInjectionStream( array1d< real64 > const & injectionStream, - real64 const & injectionTemperature, - std::string const & className, - T const & context ) -{ - GEOS_THROW_IF( (injectionStream.empty() && injectionTemperature >= 0) || - (!injectionStream.empty() && injectionTemperature < 0), - className << " " << context.getDataContext() << ": Both " - << constraintViewStruct::injectionStreamKey::injectionStreamString() << " and " << constraintViewStruct::injectionStreamKey::injectionTemperatureString() - << " must be specified for multiphase simulations", - InputError ); - - if( !injectionStream.empty()) - { - real64 sum = 0.0; - for( localIndex ic = 0; ic < injectionStream.size(); ++ic ) - { - GEOS_ERROR_IF( injectionStream[ic] < 0.0 || injectionStream[ic] > 1.0, - context.getWrapperDataContext( constraintViewStruct::injectionStreamKey::injectionStreamString() ) << ": Invalid injection stream" ); - sum += injectionStream[ic]; - } - GEOS_THROW_IF( LvArray::math::abs( 1.0 - sum ) > std::numeric_limits< real64 >::epsilon(), - context.getWrapperDataContext( constraintViewStruct::injectionStreamKey::injectionStreamString() ) << ": Invalid injection stream", - InputError ); - } -} - enum class ConstraintTypeId : integer { @@ -199,7 +165,13 @@ enum class ConstraintTypeId : integer class WellConstraintBase : public dataRepository::Group { public: + friend class WellControls; + /// Catalog interface specific to WellConstraintBase + using CatalogInterface = dataRepository::CatalogInterface< WellConstraintBase, string const &, dataRepository::Group * const >; + + /// Get the singleton catalog for WellConstraintBase + static CatalogInterface::CatalogType & getCatalog(); /** * @name Constructor / Destructor @@ -257,12 +229,6 @@ class WellConstraintBase : public dataRepository::Group // Temp interface - tjb virtual ConstraintTypeId getControl() const = 0; - /** - * @brief Get name of constraint - * @return constraint key - */ - virtual std::string getConstraintKey( ) const = 0; - /** * @brief Defines whether the constraint should be evaluated or not * @brief Some workflows require the well model to define a constraint @@ -473,7 +439,8 @@ class ProductionConstraint : public WellConstraintBase virtual void postInputInitialization() override; - + static bool isViolated( const real64 & currentValue, const real64 & constraintValue ) + { return currentValue < constraintValue; } }; /** @@ -553,6 +520,8 @@ class InjectionConstraint : public WellConstraintBase protected: virtual void postInputInitialization() override; + static bool isViolated( const real64 & currentValue, const real64 & constraintValue ) + { return currentValue > constraintValue; } void validateInjectionStream(); private: diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index 160004383d0..af821d219a6 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -41,7 +41,6 @@ WellControls::WellControls( string const & name, Group * const parent ) m_rateSign( -1.0 ), m_statusTable( nullptr ), m_wellOpen( false ), - m_estimateSolution( 0 ), m_constraintSwitch( true ), m_currentConstraint( nullptr ), m_wellStatus( WellControls::Status::OPEN ), @@ -129,46 +128,45 @@ Group * WellControls::createChild( string const & childKey, string const & child } else if( childKey == viewKeyStruct::phaseProductionConstraintString() ) { - //PhaseProductionConstraint & phaseConstraint = registerGroup< PhaseProductionConstraint >( childName ); - PhaseProductionConstraint1 & phaseConstraint = registerGroup< PhaseProductionConstraint1 >( childName ); + PhaseConstraint< ProductionConstraint > & phaseConstraint = registerGroup< PhaseConstraint< ProductionConstraint > >( childName ); m_productionRateConstraintList.emplace_back( &phaseConstraint ); constraint = &phaseConstraint; } else if( childKey == viewKeyStruct::phaseInjectionConstraintString() ) { - //PhaseInjectionConstraint & phaseConstraint = registerGroup< PhaseInjectionConstraint >( childName ); - PhaseInjectionConstraint1 & phaseConstraint = registerGroup< PhaseInjectionConstraint1 >( childName ); + + PhaseConstraint< InjectionConstraint > & phaseConstraint = registerGroup< PhaseConstraint< InjectionConstraint > >( childName ); m_injectionRateConstraintList.emplace_back( &phaseConstraint ); constraint = &phaseConstraint; } else if( childKey == viewKeyStruct::totalVolProductionConstraintString() ) { - TotalVolProductionConstraint & volConstraint = registerGroup< TotalVolProductionConstraint >( childName ); + TotalVolConstraint< ProductionConstraint > & volConstraint = registerGroup< TotalVolConstraint< ProductionConstraint > >( childName ); m_productionRateConstraintList.emplace_back( &volConstraint ); constraint = &volConstraint; } else if( childKey == viewKeyStruct::totalVolInjectionConstraintString() ) { - TotalVolInjectionConstraint & volConstraint = registerGroup< TotalVolInjectionConstraint >( childName ); + TotalVolConstraint< InjectionConstraint > & volConstraint = registerGroup< TotalVolConstraint< InjectionConstraint > >( childName ); m_injectionRateConstraintList.emplace_back( &volConstraint ); constraint = &volConstraint; } else if( childKey == viewKeyStruct::massProductionConstraintString() ) { - MassProductionConstraint & massConstraint = registerGroup< MassProductionConstraint >( childName ); + MassConstraint< ProductionConstraint > & massConstraint = registerGroup< MassConstraint< ProductionConstraint > >( childName ); m_productionRateConstraintList.emplace_back( &massConstraint ); constraint = &massConstraint; } else if( childKey == viewKeyStruct::massInjectionConstraintString() ) { - MassInjectionConstraint & massConstraint = registerGroup< MassInjectionConstraint >( childName ); + MassConstraint< InjectionConstraint > & massConstraint = registerGroup< MassConstraint< InjectionConstraint > >( childName ); m_injectionRateConstraintList.emplace_back( &massConstraint ); constraint = &massConstraint; } else if( childKey == viewKeyStruct::liquidProductionConstraintString() ) { - LiquidProductionConstraint & liquidConstraint = registerGroup< LiquidProductionConstraint >( childName ); + LiquidConstraint< ProductionConstraint > & liquidConstraint = registerGroup< LiquidConstraint< ProductionConstraint > >( childName ); m_productionRateConstraintList.emplace_back( &liquidConstraint ); constraint = &liquidConstraint; } @@ -265,12 +263,31 @@ void WellControls::setWellStatus( real64 const & currentTime, WellControls::Stat m_wellStatus = status; if( m_wellStatus == WellControls::Status::OPEN ) { - - if( isZero( getTargetTotalRate( currentTime ) ) && isZero( getTargetPhaseRate( currentTime ) ) - && isZero( getTargetMassRate( currentTime ) ) ) + if( isProducer()) { - m_wellStatus = WellControls::Status::CLOSED; + std::vector< WellConstraintBase * > const constraints = getProdRateConstraints(); + for( auto const & constraint : constraints ) + { + if( isZero( constraint->getConstraintValue( currentTime ) ) ) + { + m_wellStatus = WellControls::Status::CLOSED; + break; + } + } } + else + { + std::vector< WellConstraintBase * > const constraints = getInjRateConstraints(); + for( auto const & constraint : constraints ) + { + if( isZero( constraint->getConstraintValue( currentTime ) ) ) + { + m_wellStatus = WellControls::Status::CLOSED; + break; + } + } + } + if( m_statusTable->evaluate( ¤tTime ) < LvArray::NumericLimits< real64 >::epsilon ) { m_wellStatus = WellControls::Status::CLOSED; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp index 082a57db8a4..5421d7c7e7f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp @@ -32,7 +32,7 @@ #include "physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp" #include "physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp" #include "constitutive/fluid/multifluid/MultiFluidBase.hpp" - +#include "constitutive/fluid/singlefluid/SingleFluidBase.hpp" namespace geos { namespace dataRepository @@ -216,7 +216,18 @@ class WellControls : public dataRepository::Group } return injectionStream; } - + /** + * @brief Return the reference elvation where pressure constraint is measured + * @return vertical location of constraint + */ + real64 getReferenceElevation() const + { + if( isProducer () ) + { + return getMinBHPConstraint()->getReferenceElevation(); + } + return getMaxBHPConstraint()->getReferenceElevation(); + } /** * @brief Getter for the flag specifying whether we check rates at surface or reservoir conditions * @return 1 if we use surface conditions, and 0 otherwise @@ -302,6 +313,13 @@ class WellControls : public dataRepository::Group */ constitutive::MultiFluidBase & getMultiFluidSeparator() { return dynamicCast< constitutive::MultiFluidBase & >( *m_fluidSeparatorPtr ); } + /** + * @brief Getter for single fluid separator + * @return reference to separator + */ + constitutive::SingleFluidBase & getSingleFluidSeparator() { return dynamicCast< constitutive::SingleFluidBase & >( *m_fluidSeparatorPtr ); } + + /** * @brief Getter for the reservoir average pressure when m_useSurfaceConditions == 0 * @return the pressure diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.cpp index bb8cf202dd9..43d017d36c6 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.cpp @@ -29,57 +29,51 @@ namespace geos using namespace dataRepository; -// *** Liquid Constraint for Production Well *************************************************************** -LiquidConstraint::LiquidConstraint( string const & name, Group * const parent ) - : WellConstraintBase( name, parent ) +template< typename WellConstraintType > +LiquidConstraint< WellConstraintType >::LiquidConstraint( string const & name, Group * const parent ) + : WellConstraintType( name, parent ) { - setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); - registerWrapper( viewKeyStruct::liquidRateString(), &m_constraintValue ). + this->registerWrapper( viewKeyStruct::liquidRateString(), &this->m_constraintValue ). setDefaultValue( 0.0 ). setInputFlag( InputFlags::OPTIONAL ). setRestartFlags( RestartFlags::WRITE_AND_READ ). - setDescription( "Phase rate, (if useSurfaceConditions: [surface m^3/s]; else [reservoir m^3/s]) " ); + setDescription( "Phase rate, (if useSurfaceCondSitions: [surface m^3/s]; else [reservoir m^3/s]) " ); - registerWrapper( viewKeyStruct::phaseNamesString(), &m_phaseNames ). + this->registerWrapper( viewKeyStruct::phaseNamesString(), &m_phaseNames ). setRTTypeName( rtTypes::CustomTypes::groupNameRef ). setDefaultValue( "" ). setInputFlag( InputFlags::OPTIONAL ). setRestartFlags( RestartFlags::WRITE_AND_READ ). setDescription( "Name of the target phase" ); } - -LiquidConstraint::~LiquidConstraint() +template< typename WellConstraintType > +LiquidConstraint< WellConstraintType >::~LiquidConstraint() {} - -void LiquidConstraint::postInputInitialization() +template< typename WellConstraintType > +void LiquidConstraint< WellConstraintType >::postInputInitialization() { // Validate value and table options WellConstraintBase::postInputInitialization(); } - -// *** Liquid Constraint for Production Well *************************************************************** -LiquidProductionConstraint::LiquidProductionConstraint( string const & name, Group * const parent ) - : LiquidConstraint( name, parent ) +template< typename WellConstraintType > +bool LiquidConstraint< WellConstraintType >::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const { - m_rateSign=-1.0; + return WellConstraintType::isViolated( currentConstraint.liquidRate(), this->getConstraintValue( currentTime )); } -LiquidProductionConstraint::~LiquidProductionConstraint() -{} - -void LiquidProductionConstraint::postInputInitialization() +namespace { - // Validate value and table options - LiquidConstraint::postInputInitialization(); -} +typedef LiquidConstraint< InjectionConstraint > LiquidInjectionConstraint; +REGISTER_CATALOG_ENTRY( WellConstraintBase, LiquidInjectionConstraint, string const &, Group * const ) +typedef LiquidConstraint< ProductionConstraint > LiquidProductionConstraint; +REGISTER_CATALOG_ENTRY( WellConstraintBase, LiquidProductionConstraint, string const &, Group * const ) -bool LiquidProductionConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const -{ - return currentConstraint.liquidRate() < getConstraintValue( currentTime ); } - +// Explicit template instantiations to ensure constructors are emitted for registration +template class LiquidConstraint< InjectionConstraint >; +template class LiquidConstraint< ProductionConstraint >; } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp index d8fce1733b4..bd9938c1510 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp @@ -32,10 +32,11 @@ namespace geos /** * @class LiquidConstraint - * @brief This class describes a Liquid rate constraint used to control a production well. + * @brief This class describes a Liquid rate constraint used to control of type WellConstraintType */ -class LiquidConstraint : public WellConstraintBase +template< typename WellConstraintType > +class LiquidConstraint : public WellConstraintType { public: @@ -85,6 +86,21 @@ class LiquidConstraint : public WellConstraintBase */ LiquidConstraint & operator=( LiquidConstraint && ) = delete; + /** + * @brief name of the node manager in the object catalog + * @return string that contains the catalog name to generate a new Constraint object through the object catalog. + */ + static string catalogName() + { + if constexpr ( std::is_same_v< WellConstraintType, InjectionConstraint > ) // special case + { + return "LiquidInjectionConstraint"; + } + else // default + { + return "LiquidProductionConstraint"; + } + } ///@} /** @@ -125,11 +141,26 @@ class LiquidConstraint : public WellConstraintBase // Temp interface - tjb virtual ConstraintTypeId getControl() const override { return ConstraintTypeId::LIQUIDRATE; }; + virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const override; protected: virtual void postInputInitialization() override; + template< typename T > + void validateLiquidType( T const & fluidModel ) + { + m_phaseIndices.resize( m_phaseNames.size()); + for( size_t ip =0; ip void validateLiquidType( T const & fluidModel ); -protected: - - virtual void postInputInitialization() override; - -}; - -template< typename T > -void LiquidProductionConstraint::validateLiquidType( T const & fluidModel ) -{ - m_phaseIndices.resize( m_phaseNames.size()); - for( size_t ip =0; ip( LiquidConstraint::viewKeyStruct::liquidRateString()) << - ": Invalid Liquid type for simulation fluid model " << m_phaseNames[ip], - InputError ); - m_phaseIndices[ip]=phaseIndex; - } -} } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.cpp index 63cc38d9918..62bc1112264 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.cpp @@ -29,81 +29,44 @@ namespace geos using namespace dataRepository; - -MassConstraint::MassConstraint( string const & name, Group * const parent ) - : WellConstraintBase( name, parent ) -{ - setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); -} - -MassConstraint::~MassConstraint() -{} - -void MassConstraint::postInputInitialization() +template< typename WellConstraintType > +MassConstraint< WellConstraintType >::MassConstraint( string const & name, Group * const parent ) + : WellConstraintType( name, parent ) { - // Validate value and table options - WellConstraintBase::postInputInitialization(); + this->setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); -} - -MassProductionConstraint::MassProductionConstraint( string const & name, Group * const parent ) - : MassConstraint( name, parent ) -{ - m_rateSign = -1.0; - setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); - registerWrapper( constraintViewStruct::constraintValueKey::constraintValueString(), &m_constraintValue ). + this->registerWrapper( constraintViewStruct::constraintValueKey::constraintValueString(), &this->m_constraintValue ). setDefaultValue( 0.0 ). setInputFlag( InputFlags::OPTIONAL ). setRestartFlags( RestartFlags::WRITE_AND_READ ). - setDescription( "Maximum mass injection rate (if useSurfaceConditions: [surface m^3/s]; else [reservoir m^3/s])" ); - + setDescription( "Maximum mass rate (kg/s)" ); } - - -MassProductionConstraint::~MassProductionConstraint() +template< typename WellConstraintType > +MassConstraint< WellConstraintType >::~MassConstraint() {} -void MassProductionConstraint::postInputInitialization() +template< typename WellConstraintType > +void MassConstraint< WellConstraintType >::postInputInitialization() { // Validate value and table options - MassConstraint::postInputInitialization(); - -} - -bool MassProductionConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const -{ - return currentConstraint.massRate() < getConstraintValue( currentTime ); -} - - -MassInjectionConstraint::MassInjectionConstraint( string const & name, Group * const parent ) - : MassConstraint( name, parent ) -{ - setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); + WellConstraintBase::postInputInitialization(); - registerWrapper( constraintViewStruct::constraintValueKey::constraintValueString(), &m_constraintValue ). - setDefaultValue( 0.0 ). - setInputFlag( InputFlags::OPTIONAL ). - setRestartFlags( RestartFlags::WRITE_AND_READ ). - setDescription( "Maximum mass injection rate (if useSurfaceConditions: [surface m^3/s]; else [reservoir m^3/s])" ); } -MassInjectionConstraint::~MassInjectionConstraint() -{} - -void MassInjectionConstraint::postInputInitialization() +template< typename WellConstraintType > +bool MassConstraint< WellConstraintType >::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime )const { - // Validate value and table options - MassConstraint::postInputInitialization(); - -// Validate the injection stream and temperature - validateInjectionStream( m_injectionStream, m_injectionTemperature, getConstraintKey(), *this ); + // isViolated is defined as a static method on the specific WellConstraintType (Injection/Production) + return WellConstraintType::isViolated( currentConstraint.massRate(), this->getConstraintValue( currentTime )); } -bool MassInjectionConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime )const -{ - return currentConstraint.massRate() > getConstraintValue( currentTime ); -} +typedef MassConstraint< InjectionConstraint > MassInjectionConstraint; +REGISTER_CATALOG_ENTRY( WellConstraintBase, MassInjectionConstraint, string const &, Group * const ) +typedef MassConstraint< ProductionConstraint > MassProductionConstraint; +REGISTER_CATALOG_ENTRY( WellConstraintBase, MassProductionConstraint, string const &, Group * const ) +// Explicit template instantiations to ensure symbols are emitted for the concrete types +template class MassConstraint< InjectionConstraint >; +template class MassConstraint< ProductionConstraint >; } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp index 41039458e32..eb7af0f8a3d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp @@ -32,8 +32,8 @@ namespace geos * @class MassConstraint * @brief This class describes a mass rate constraint used to control a well. */ - -class MassConstraint : public WellConstraintBase +template< typename WellConstraintType > +class MassConstraint : public WellConstraintType { public: @@ -82,6 +82,21 @@ class MassConstraint : public WellConstraintBase */ MassConstraint & operator=( MassConstraint && ) = delete; + /** + * @brief name of the node manager in the object catalog + * @return string that contains the catalog name to generate a new Constraint object through the object catalog. + */ + static string catalogName() + { + if constexpr ( std::is_same_v< WellConstraintType, InjectionConstraint > ) // special case + { + return "MassInjectionConstraint"; + } + else // default + { + return "MassProductionConstraint"; + } + } ///@} /** @@ -92,181 +107,14 @@ class MassConstraint : public WellConstraintBase virtual ConstraintTypeId getControl() const override { return ConstraintTypeId::MASSRATE; }; ///@} - -protected: - - virtual void postInputInitialization() override; - - - -}; - - -/** - * @class MassProductionConstraint - * @brief This class describes a mass rate constraint used to control a production well. - */ - -class MassProductionConstraint : public MassConstraint -{ -public: - - /** - * @name Constructor / Destructor - */ - ///@{ - - /** - * @brief Constructor for WellControls Objects. - * @param[in] name the name of this instantiation of WellControls in the repository - * @param[in] parent the parent group of this instantiation of WellControls - */ - explicit MassProductionConstraint( string const & name, dataRepository::Group * const parent ); - - - /** - * @brief Default destructor. - */ - ~MassProductionConstraint() override; - - /** - * @brief Deleted default constructor. - */ - MassProductionConstraint() = delete; - - /** - * @brief Deleted copy constructor. - */ - MassProductionConstraint( MassProductionConstraint const & ) = delete; - - /** - * @brief Deleted move constructor. - */ - MassProductionConstraint( MassProductionConstraint && ) = delete; - - /** - * @brief Deleted assignment operator. - * @return a reference to a constraint object - */ - MassProductionConstraint & operator=( MassProductionConstraint const & ) = delete; - - /** - * @brief Deleted move operator. - * @return a reference to a constraint object - */ - MassProductionConstraint & operator=( MassProductionConstraint && ) = delete; - - ///@} - - /** - * @name Getters / Setters - */ - - /** - * @brief Get name of constraint - * @return constraint key - */ - virtual std::string getConstraintKey( ) const override { return "MassProductionConstraint"; }; - ///@} - virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const override; protected: virtual void postInputInitialization() override; - - }; -/** - * @class MassInjectionConstraint - * @brief This class describes a Mass rate constraint used to control a injection well. - */ - -class MassInjectionConstraint : public MassConstraint -{ -public: - - - /** - * @name Constructor / Destructor - */ - ///@{ - - /** - * @brief Constructor for MassInjectionConstraint Objects. - * @param[in] name the name of this instantiation of WellControls in the repository - * @param[in] parent the parent group of this instantiation of WellControls - */ - explicit MassInjectionConstraint( string const & name, dataRepository::Group * const parent ); - - - /** - * @brief Default destructor. - */ - ~MassInjectionConstraint() override; - - /** - * @brief Deleted default constructor. - */ - MassInjectionConstraint() = delete; - - /** - * @brief Deleted copy constructor. - */ - MassInjectionConstraint( MassInjectionConstraint const & ) = delete; - - /** - * @brief Deleted move constructor. - */ - MassInjectionConstraint( MassInjectionConstraint && ) = delete; - - /** - * @brief Deleted assignment operator. - * @return a reference to a constraint object - */ - MassInjectionConstraint & operator=( MassInjectionConstraint const & ) = delete; - - /** - * @brief Deleted move operator. - * @return a reference to a constraint object - */ - MassInjectionConstraint & operator=( MassInjectionConstraint && ) = delete; - - ///@} - - /** - * @name Getters / Setters - */ - ///@{ - /** - * @brief Get name of constraint - * @return constraint key - */ - virtual std::string getConstraintKey( ) const override { return "MassInjectionConstraint"; }; - ///@} - - // Injection stream definition keys - constraintViewStruct::injectionStreamKey viewKeysInjectionStream; - - virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const override; - -protected: - - virtual void postInputInitialization() override; - -private: - - /// Vector with global component fractions at the injector - array1d< real64 > m_injectionStream; - - /// Temperature at the injector - real64 m_injectionTemperature; - -}; - - } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.cpp index 83fb53b4658..11d3a460d4e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.cpp @@ -29,125 +29,20 @@ namespace geos using namespace dataRepository; -// *** Phase Constraint for Production Well *************************************************************** -PhaseConstraint::PhaseConstraint( string const & name, Group * const parent ) - : WellConstraintBase( name, parent ), - m_phaseIndex( -1 ) -{ - setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); - - registerWrapper( viewKeyStruct::phaseRateString(), &m_constraintValue ). - setDefaultValue( 0.0 ). - setInputFlag( InputFlags::OPTIONAL ). - setRestartFlags( RestartFlags::WRITE_AND_READ ). - setDescription( "Phase rate, (if useSurfaceConditions: [surface m^3/s]; else [reservoir m^3/s]) " ); - - registerWrapper( viewKeyStruct::phaseNameString(), &m_phaseName ). - setRTTypeName( rtTypes::CustomTypes::groupNameRef ). - setDefaultValue( "" ). - setInputFlag( InputFlags::OPTIONAL ). - setRestartFlags( RestartFlags::WRITE_AND_READ ). - setDescription( "Name of the target phase" ); - - if constexpr ( std::is_same_v< WellType, WellTypes::Injector > ) - { - registerWrapper( injectionStreamKey::injectionStreamString(), &m_injectionStream ). - setDefaultValue( -1 ). - setSizedFromParent( 0 ). - setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Global component densities of the injection stream [moles/m^3 or kg/m^3]" ); - - registerWrapper( injectionStreamKey::injectionTemperatureString(), &m_injectionTemperature ). - setDefaultValue( -1 ). - setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Temperature of the injection stream [K]" ); - } -} - -PhaseConstraint::~PhaseConstraint() -{} - -void PhaseConstraint::postInputInitialization() -{ - // Validate value and table options - WellConstraintBase::postInputInitialization(); -} - - -// *** Phase Constraint for Production Well *************************************************************** -PhaseProductionConstraint::PhaseProductionConstraint( string const & name, Group * const parent ) - : PhaseConstraint( name, parent ) -{ - m_rateSign=-1.0; -} - -PhaseProductionConstraint::~PhaseProductionConstraint() -{} - -void PhaseProductionConstraint::postInputInitialization() -{ - // Validate value and table options - PhaseConstraint::postInputInitialization(); - -} - -bool PhaseProductionConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const -{ - return currentConstraint.phaseVolumeRates()[m_phaseIndex] < getConstraintValue( currentTime ); -} - - - -// *** Phase Constraint for Injection Well *************************************************************** -PhaseInjectionConstraint::PhaseInjectionConstraint( string const & name, Group * const parent ) - : PhaseConstraint( name, parent ) -{ - registerWrapper( constraintViewStruct::injectionStreamKey::injectionStreamString(), &m_injectionStream ). - setDefaultValue( -1 ). - setSizedFromParent( 0 ). - setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Global component densities of the injection stream [moles/m^3 or kg/m^3]" ); - - registerWrapper( constraintViewStruct::injectionStreamKey::injectionTemperatureString(), &m_injectionTemperature ). - setDefaultValue( -1 ). - setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Temperature of the injection stream [K]" ); -} - - -PhaseInjectionConstraint::~PhaseInjectionConstraint() -{} - -void PhaseInjectionConstraint::postInputInitialization() -{ - - // Validate value and table options - PhaseConstraint::postInputInitialization(); - -// Validate the injection stream and temperature - validateInjectionStream( m_injectionStream, m_injectionTemperature, getConstraintKey(), *this ); - -} - -bool PhaseInjectionConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const -{ - return currentConstraint.phaseVolumeRates()[m_phaseIndex] > getConstraintValue( currentTime ); -} template< typename WellConstraintType > -PhaseConstraint1< WellConstraintType >::PhaseConstraint1( string const & name, Group * const parent ) +PhaseConstraint< WellConstraintType >::PhaseConstraint( string const & name, Group * const parent ) : WellConstraintType( name, parent ) { + this->setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); - setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); - - registerWrapper( viewKeyStruct::phaseRateString(), &m_constraintValue ). + this->registerWrapper( viewKeyStruct::phaseRateString(), &this->m_constraintValue ). setDefaultValue( 0.0 ). setInputFlag( InputFlags::OPTIONAL ). setRestartFlags( RestartFlags::WRITE_AND_READ ). setDescription( "Phase rate, (if useSurfaceConditions: [surface m^3/s]; else [reservoir m^3/s]) " ); - registerWrapper( viewKeyStruct::phaseNameString(), &m_phaseName ). + this->registerWrapper( viewKeyStruct::phaseNameString(), &this->m_phaseName ). setRTTypeName( rtTypes::CustomTypes::groupNameRef ). setDefaultValue( "" ). setInputFlag( InputFlags::OPTIONAL ). @@ -155,31 +50,34 @@ PhaseConstraint1< WellConstraintType >::PhaseConstraint1( string const & name, G setDescription( "Name of the target phase" ); } -PhaseConstraint1< WellConstraintType >::~PhaseConstraint1() +template< typename WellConstraintType > +PhaseConstraint< WellConstraintType >::~PhaseConstraint() {} -void PhaseConstraint1< WellConstraintType >::postInputInitialization() +template< typename WellConstraintType > +void PhaseConstraint< WellConstraintType >::postInputInitialization() { // Validate value and table options WellConstraintType::postInputInitialization(); - } -bool PhaseConstraint1< WellConstraintType >::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const +template< typename WellConstraintType > +bool PhaseConstraint< WellConstraintType >::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const { - return currentConstraint.phaseVolumeRates()[m_phaseIndex] > getConstraintValue( currentTime ); + return this->isViolated( currentConstraint.phaseVolumeRates()[this->m_phaseIndex], this->getConstraintValue( currentTime )); } namespace { -//typedef MultiphasePoromechanicsConformingFractures< MultiphaseReservoirAndWells<> > -// MultiphasePoromechanicsConformingFractures; -//REGISTER_CATALOG_ENTRY( PhysicsSolverBase, MultiphasePoromechanicsConformingFractures, string const &, Group * const ) -typedef PhaseConstraint1< InjectionConstraint > PhaseInjectionConstraint1; -REGISTER_CATALOG_ENTRY( WellConstraintBase, PhaseInjectionConstraint1, string const &, Group * const ) -typedef PhaseConstraint1< ProductionConstraint > PhaseProductionConstraint1; -REGISTER_CATALOG_ENTRY( WellConstraintBase, PhaseProductionConstraint1, string const &, Group * const ) + +typedef PhaseConstraint< InjectionConstraint > PhaseInjectionConstraint; +REGISTER_CATALOG_ENTRY( WellConstraintBase, PhaseInjectionConstraint, string const &, Group * const ) +typedef PhaseConstraint< ProductionConstraint > PhaseProductionConstraint; +REGISTER_CATALOG_ENTRY( WellConstraintBase, PhaseProductionConstraint, string const &, Group * const ) } +// Explicit template instantiations to ensure constructors are emitted for registration +template class PhaseConstraint< InjectionConstraint >; +template class PhaseConstraint< ProductionConstraint >; } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp index 02fd0e0316b..3345882e6e8 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp @@ -48,10 +48,10 @@ localIndex getPhaseIndexFromFluidModel( T const & fluidModel, std::string const /** * @class PhaseConstraint - * @brief This class describes a phase rate constraint used to control a production well. + * @brief This class describes a phase rate constraint used to control a well of WellConstraintType type (Injection or Production). */ - -class PhaseConstraint : public WellConstraintBase +template< typename WellConstraintType > +class PhaseConstraint : public WellConstraintType { public: @@ -68,7 +68,6 @@ class PhaseConstraint : public WellConstraintBase */ explicit PhaseConstraint( string const & name, dataRepository::Group * const parent ); - /** * @brief Default destructor. */ @@ -103,309 +102,9 @@ class PhaseConstraint : public WellConstraintBase ///@} - - - /** - * @name Getters / Setters - */ - ///@{ - - // Temp interface - tjb - virtual ConstraintTypeId getControl() const override { return ConstraintTypeId::PHASEVOLRATE; }; - - /** - * @brief Get the target phase name - * @return the target phase name - */ - const string & getPhaseName() const { return m_phaseName; } - - /** - * @brief Get the target phase index - * @return the target phase index - */ - const localIndex & getPhaseIndex() const { return m_phaseIndex; } - - ///@} - - struct viewKeyStruct - { - /// String key for the well target phase rate - static constexpr char const * phaseRateString() { return "phaseRate"; } - /// String key for the well target phase name - static constexpr char const * phaseNameString() { return "phaseName"; } - }; - -protected: - - virtual void postInputInitialization() override; - -protected: - /// Name of the targeted phase - string m_phaseName; - - /// Index of the target phase, used to impose the phase rate constraint - localIndex m_phaseIndex; - -}; - - -/** - * @class PhaseProductionConstraint - * @brief This class describes a phase rate constraint used to control a production well. - */ - -class PhaseProductionConstraint : public PhaseConstraint -{ -public: - - - /** - * @name Constructor / Destructor - */ - ///@{ - - /** - * @brief Constructor for WellControls Objects. - * @param[in] name the name of this instantiation of WellControls in the repository - * @param[in] parent the parent group of this instantiation of WellControls - */ - explicit PhaseProductionConstraint( string const & name, dataRepository::Group * const parent ); - - - /** - * @brief Default destructor. - */ - ~PhaseProductionConstraint() override; - - /** - * @brief Deleted default constructor. - */ - PhaseProductionConstraint() = delete; - - /** - * @brief Deleted copy constructor. - */ - PhaseProductionConstraint( PhaseProductionConstraint const & ) = delete; - - /** - * @brief Deleted move constructor. - */ - PhaseProductionConstraint( PhaseProductionConstraint && ) = delete; - - /** - * @brief Deleted assignment operator. - * @return a reference to a constraint object - */ - PhaseProductionConstraint & operator=( PhaseProductionConstraint const & ) = delete; - - /** - * @brief Deleted move operator. - * @return a reference to a constraint object - */ - PhaseProductionConstraint & operator=( PhaseProductionConstraint && ) = delete; - - ///@} - - /** - * @name Getters / Setters - */ - ///@{ - - /** - * @brief Get name of constraint - * @return constraint key - */ - virtual std::string getConstraintKey( ) const override { return "PhaseProductionConstraint"; }; - - - virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const override; - ///@} - - /** - * @brief Validate phase type is consistent with fluidmodel - */ - template< typename T > void validatePhaseType( T const & fluidModel ); -protected: - - virtual void postInputInitialization() override; - -}; - -template< typename T > -void PhaseProductionConstraint::validatePhaseType( T const & fluidModel ) -{ - // Find target phase index for phase rate constraint - m_phaseIndex = getPhaseIndexFromFluidModel( fluidModel, getReference< string >( PhaseConstraint::viewKeyStruct::phaseNameString())); - - GEOS_THROW_IF( m_phaseIndex == -1, - "PhaseProductionConstraint " << getReference< string >( PhaseConstraint::viewKeyStruct::phaseNameString()) << - ": Invalid phase type for simulation fluid model", - InputError ); -} - -/** - * @class PhaseInjectionConstraint - * @brief This class describes a phase rate constraint used to control a injection well. - */ - -class PhaseInjectionConstraint : public PhaseConstraint -{ -public: - - - /** - * @name Constructor / Destructor - */ - ///@{ - - /** - * @brief Constructor for WellControls Objects. - * @param[in] name the name of this instantiation of WellControls in the repository - * @param[in] parent the parent group of this instantiation of WellControls - */ - explicit PhaseInjectionConstraint( string const & name, dataRepository::Group * const parent ); - - - /** - * @brief Default destructor. - */ - ~PhaseInjectionConstraint() override; - - /** - * @brief Deleted default constructor. - */ - PhaseInjectionConstraint() = delete; - - /** - * @brief Deleted copy constructor. - */ - PhaseInjectionConstraint( PhaseInjectionConstraint const & ) = delete; - - /** - * @brief Deleted move constructor. - */ - PhaseInjectionConstraint( PhaseInjectionConstraint && ) = delete; - - /** - * @brief Deleted assignment operator. - * @return a reference to a constraint object - */ - PhaseInjectionConstraint & operator=( PhaseInjectionConstraint const & ) = delete; - - /** - * @brief Deleted move operator. - * @return a reference to a constraint object - */ - PhaseInjectionConstraint & operator=( PhaseInjectionConstraint && ) = delete; - - ///@} - - /** - * @name Getters / Setters - */ - ///@{ - - /** - * @brief Get name of constraint - * @return constraint key - */ - virtual std::string getConstraintKey( ) const override { return "PhaseInjectionConstraint"; }; - ///@} - - - /** - * @brief Validate phase type is consistent with fluidmodel - */ - template< typename T > void validatePhaseType( T const & fluidModel ); - ///@} - - virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const override; -protected: - - virtual void postInputInitialization() override; - -private: - - /// Vector with global component fractions at the injector - array1d< real64 > m_injectionStream; - - /// Temperature at the injector - real64 m_injectionTemperature; - -}; - - -template< typename T > -void PhaseInjectionConstraint::validatePhaseType( T const & fluidModel ) -{ - // Find target phase index for phase rate constraint - m_phaseIndex = getPhaseIndexFromFluidModel( fluidModel, getReference< string >( PhaseConstraint::viewKeyStruct::phaseNameString())); - - GEOS_THROW_IF( m_phaseIndex == -1, - "PhaseInjectionConstraint " << getReference< string >( PhaseConstraint::viewKeyStruct::phaseNameString()) << - ": Invalid phase type for simulation fluid model", - InputError ); -} - -/** - * @class PhaseInjectionConstraint - * @brief This class describes a phase rate constraint used to control a injection well. - */ -template< typename WellConstraintType > -class PhaseConstraint1 : public WellConstraintType -{ -public: - - - /** - * @name Constructor / Destructor - */ - ///@{ - - /** - * @brief Constructor for WellControls Objects. - * @param[in] name the name of this instantiation of WellControls in the repository - * @param[in] parent the parent group of this instantiation of WellControls - */ - explicit PhaseConstraint1( string const & name, dataRepository::Group * const parent ); - - /** - * @brief Default destructor. - */ - ~PhaseConstraint1() override; - - /** - * @brief Deleted default constructor. - */ - PhaseConstraint1() = delete; - - /** - * @brief Deleted copy constructor. - */ - PhaseConstraint1( PhaseConstraint1 const & ) = delete; - - /** - * @brief Deleted move constructor. - */ - PhaseConstraint1( PhaseConstraint1 && ) = delete; - - /** - * @brief Deleted assignment operator. - * @return a reference to a constraint object - */ - PhaseConstraint1 & operator=( PhaseConstraint1 const & ) = delete; - - /** - * @brief Deleted move operator. - * @return a reference to a constraint object - */ - PhaseConstraint1 & operator=( PhaseConstraint1 && ) = delete; - - ///@} - /** * @brief name of the node manager in the object catalog - * @return string that contains the catalog name to generate a new MultiphasePoromechanics object through the object catalog. + * @return string that contains the catalog name to generate a new Constraint object through the object catalog. */ static string catalogName() { @@ -472,7 +171,7 @@ class PhaseConstraint1 : public WellConstraintType template< typename WellConstraintType > template< typename T > -void PhaseConstraint1< WellConstraintType >::validatePhaseType( T const & fluidModel ) +void PhaseConstraint< WellConstraintType >::validatePhaseType( T const & fluidModel ) { // Find target phase index for phase rate constraint m_phaseIndex = getPhaseIndexFromFluidModel( fluidModel, this->template getReference< string >( viewKeyStruct::phaseNameString())); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp index d9b5c49f6c4..e05279d7d53 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp @@ -198,7 +198,7 @@ class WellSolverBase : public PhysicsSolverBase WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), DofManager const & GEOS_UNUSED_PARAM( dofManager ), CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), - arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) {}; + arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) = 0; /** @@ -219,12 +219,12 @@ class WellSolverBase : public PhysicsSolverBase - virtual void assembleWellAccumulationTerms( real64 const & GEOS_UNUSED_PARAM( time ), - real64 const & GEOS_UNUSED_PARAM( dt ), - WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ), - DofManager const & GEOS_UNUSED_PARAM( dofManager ), - CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), - arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) {}; + virtual void assembleWellAccumulationTerms( real64 const & time, + real64 const & dt, + WellElementSubRegion & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) = 0; /** @@ -246,16 +246,17 @@ class WellSolverBase : public PhysicsSolverBase WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), DofManager const & GEOS_UNUSED_PARAM( dofManager ), CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), - arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) {}; - - virtual void assembleWellPressureRelations( real64 const & GEOS_UNUSED_PARAM( time ), - real64 const & GEOS_UNUSED_PARAM( dt ), - WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), - DofManager const & GEOS_UNUSED_PARAM( dofManager ), - CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), - arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) {}; + arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) = 0; + + virtual void assembleWellPressureRelations ( real64 const & GEOS_UNUSED_PARAM( time ), + real64 const & GEOS_UNUSED_PARAM( dt ), + WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ), + CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), + arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) = 0; /** - * @brief assembles the pressure relations at all connections between well elements except at the well head + * @brief assembles the pressure relations at all connections between well elements except at + * the well head * @param time_n time at the beginning of the time step * @param dt the time step size * @param domain the physical domain object @@ -271,15 +272,18 @@ class WellSolverBase : public PhysicsSolverBase arrayView1d< real64 > const & localRhs ) = 0; /** - * @brief Recompute all dependent quantities from primary variables (including constitutive models) + * @brief Recompute all dependent quantities from primary variables (including constitutive + * models) * @param domain the domain containing the mesh and fields */ - virtual real64 updateWellState( WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ) ){return 0.0;}; + virtual real64 updateWellState( WellElementSubRegion & subRegion ) = 0; virtual void updateState( DomainPartition & domain ) override; /** - * @brief Recompute all dependent quantities from primary variables (including constitutive models) - * @param subRegion the well subRegion containing the well elements and their associated fields + * @brief Recompute all dependent quantities from primary variables (including constitutive + * models) + * @param subRegion the well subRegion containing the well elements and their associated + * fields */ virtual real64 updateSubRegionState( WellElementSubRegion & subRegion ) = 0; @@ -302,26 +306,26 @@ class WellSolverBase : public PhysicsSolverBase real64 const & GEOS_UNUSED_PARAM( dt ), WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), DofManager const & GEOS_UNUSED_PARAM( dofManager ), - arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localRhs ) ) {return std::numeric_limits< real64 >::max();}; + arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localRhs ) ) = 0; virtual real64 - scalingForWellSystemSolution( ElementSubRegionBase & GEOS_UNUSED_PARAM( subRegion ), - DofManager const & GEOS_UNUSED_PARAM( dofManager ), - arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localSolution ) ) {return std::numeric_limits< real64 >::max();}; + scalingForWellSystemSolution( ElementSubRegionBase & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ), + arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localSolution ) ) = 0; virtual bool - checkWellSystemSolution( ElementSubRegionBase & GEOS_UNUSED_PARAM( subRegion ), - DofManager const & GEOS_UNUSED_PARAM( dofManager ), - arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localSolution ), - real64 const GEOS_UNUSED_PARAM( scalingFactor ) ) {return false;}; + checkWellSystemSolution( ElementSubRegionBase & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ), + arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localSolution ), + real64 const GEOS_UNUSED_PARAM( scalingFactor ) ) = 0; virtual void - applyWellSystemSolution( DofManager const & GEOS_UNUSED_PARAM( dofManager ), - arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localSolution ), - real64 const GEOS_UNUSED_PARAM( scalingFactor ), - real64 const GEOS_UNUSED_PARAM( dt ), - DomainPartition & GEOS_UNUSED_PARAM( domain ), - MeshLevel & GEOS_UNUSED_PARAM( mesh ), - WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ) ) {}; + applyWellSystemSolution( DofManager const & GEOS_UNUSED_PARAM( dofManager ), + arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localSolution ), + real64 const GEOS_UNUSED_PARAM( scalingFactor ), + real64 const GEOS_UNUSED_PARAM( dt ), + DomainPartition & GEOS_UNUSED_PARAM( domain ), + MeshLevel & GEOS_UNUSED_PARAM( mesh ), + WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ) ) = 0; /** * @brief Function to perform line search @@ -334,10 +338,12 @@ class WellSolverBase : public PhysicsSolverBase * @param rhs the system right-hand side vector * @param solution the solution vector * @param scaleFactor the scaling factor to apply to the solution - * @param lastResidual (in) target value below which to reduce residual norm, (out) achieved residual norm + * @param lastResidual (in) target value below which to reduce residual norm, (out) achieved + * residual norm * @return return true if line search succeeded, false otherwise * - * This function implements a nonlinear newton method for implicit problems. It requires that the + * This function implements a nonlinear newton method for implicit problems. It requires that + * the * other functions in the solver interface are implemented in the derived physics solver. The * nonlinear loop includes a simple line search algorithm, and will cut the timestep if * convergence is not achieved according to the parameters in linearSolverParameters member. @@ -368,9 +374,12 @@ class WellSolverBase : public PhysicsSolverBase DomainPartition & domain ) override; /** - * @brief Utility function to keep the well variables during a time step (used in poromechanics simulations) - * @param[in] keepVariablesConstantDuringInitStep flag to tell the solver to freeze its primary variables during a time step - * @detail This function is meant to be called by a specific task before/after the initialization step + * @brief Utility function to keep the well variables during a time step (used in + * poromechanics simulations) + * @param[in] keepVariablesConstantDuringInitStep flag to tell the solver to freeze its + * primary variables during a time step + * @detail This function is meant to be called by a specific task before/after the + * initialization step */ void setKeepVariablesConstantDuringInitStep( bool const keepVariablesConstantDuringInitStep ) { m_keepVariablesConstantDuringInitStep = keepVariablesConstantDuringInitStep; } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.cpp index 5094cdc761f..167b6467864 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.cpp @@ -29,11 +29,13 @@ namespace geos using namespace dataRepository; -TotalVolConstraint::TotalVolConstraint( string const & name, Group * const parent ) - : WellConstraintBase( name, parent ) +template< typename WellConstraintType > +TotalVolConstraint< WellConstraintType >::TotalVolConstraint( string const & name, Group * const parent ) + : WellConstraintType( name, parent ) { - setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); - registerWrapper( viewKeyStruct::volumeRateString(), &m_constraintValue ). + this->setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); + + this->registerWrapper( viewKeyStruct::volumeRateString(), &this->m_constraintValue ). setDefaultValue( 0.0 ). setInputFlag( InputFlags::OPTIONAL ). setRestartFlags( RestartFlags::WRITE_AND_READ ). @@ -41,59 +43,30 @@ TotalVolConstraint::TotalVolConstraint( string const & name, Group * const paren } - -TotalVolConstraint::~TotalVolConstraint() +template< typename WellConstraintType > +TotalVolConstraint< WellConstraintType >::~TotalVolConstraint() {} -void TotalVolConstraint::postInputInitialization() +template< typename WellConstraintType > +void TotalVolConstraint< WellConstraintType >::postInputInitialization() { WellConstraintBase::postInputInitialization(); - -} - - -TotalVolProductionConstraint::TotalVolProductionConstraint( string const & name, Group * const parent ) - : TotalVolConstraint( name, parent ) -{ - setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); - -} - - -TotalVolProductionConstraint::~TotalVolProductionConstraint() -{} - -void TotalVolProductionConstraint::postInputInitialization() -{ - TotalVolConstraint::postInputInitialization(); - } -bool TotalVolProductionConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime )const +template< typename WellConstraintType > +bool TotalVolConstraint< WellConstraintType >::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime )const { - return currentConstraint.totalVolumeRate() < getConstraintValue( currentTime ); + return WellConstraintType::isViolated( currentConstraint.totalVolumeRate(), this->getConstraintValue( currentTime )); } +typedef TotalVolConstraint< InjectionConstraint > TotalVolInjectionConstraint; +REGISTER_CATALOG_ENTRY( WellConstraintBase, TotalVolInjectionConstraint, string const &, Group * const ) +typedef TotalVolConstraint< ProductionConstraint > TotalVolProductionConstraint; +REGISTER_CATALOG_ENTRY( WellConstraintBase, TotalVolProductionConstraint, string const &, Group * const ) -TotalVolInjectionConstraint::TotalVolInjectionConstraint( string const & name, Group * const parent ) - : TotalVolConstraint( name, parent ) -{ - setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); -} - - -TotalVolInjectionConstraint::~TotalVolInjectionConstraint() -{} - -void TotalVolInjectionConstraint::postInputInitialization() -{ - TotalVolConstraint::postInputInitialization(); -} - -bool TotalVolInjectionConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime )const -{ - return currentConstraint.totalVolumeRate() > getConstraintValue( currentTime ); -} +// Explicit template instantiations to ensure constructors are emitted for registration +template class TotalVolConstraint< InjectionConstraint >; +template class TotalVolConstraint< ProductionConstraint >; } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp index 90d8cf36211..3e7dc4a5e27 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp @@ -27,22 +27,15 @@ #include "WellConstraintsBase.hpp" namespace geos { -namespace dataRepository -{ -namespace keys -{ -static constexpr auto totalVolProductionConstraint = "TotalVolProductionConstraint"; -static constexpr auto totalVolInjectionConstraint = "TotalVolInjectionConstraint"; -} -} + /** * @class TotalVolConstraint * @brief This class describes a volume rate constraint used to control a well. */ - -class TotalVolConstraint : public WellConstraintBase +template< typename WellConstraintType > +class TotalVolConstraint : public WellConstraintType { public: @@ -91,6 +84,21 @@ class TotalVolConstraint : public WellConstraintBase */ TotalVolConstraint & operator=( TotalVolConstraint && ) = delete; + /** + * @brief name of the node manager in the object catalog + * @return string that contains the catalog name to generate a new Constraint object through the object catalog. + */ + static string catalogName() + { + if constexpr ( std::is_same_v< WellConstraintType, InjectionConstraint > ) // special case + { + return "TotalVolInjectionConstraint"; + } + else // default + { + return "TotalVolProductionConstraint"; + } + } ///@} /** * @brief Struct to serve as a container for variable strings and keys. @@ -105,182 +113,19 @@ class TotalVolConstraint : public WellConstraintBase * @name Getters / Setters */ ///@{ - /** - * @brief Get name of constraint - * @return constraint key - */ - virtual std::string getConstraintKey( ) const override { return "TotalVolInjectionConstraint"; }; - ///@} // Temp interface - tjb virtual ConstraintTypeId getControl() const override { return ConstraintTypeId::TOTALVOLRATE; }; - -protected: - - virtual void postInputInitialization() override; - -}; - - -/** - * @class TotalVolProductionConstraint - * @brief This class describes a volume rate constraint used to control a production well. - */ - -class TotalVolProductionConstraint : public TotalVolConstraint -{ -public: - - /** - * @name Constructor / Destructor - */ - ///@{ - - /** - * @brief Constructor for WellControls Objects. - * @param[in] name the name of this instantiation of WellControls in the repository - * @param[in] parent the parent group of this instantiation of WellControls - */ - explicit TotalVolProductionConstraint( string const & name, dataRepository::Group * const parent ); - - - /** - * @brief Default destructor. - */ - ~TotalVolProductionConstraint() override; - - /** - * @brief Deleted default constructor. - */ - TotalVolProductionConstraint() = delete; - - /** - * @brief Deleted copy constructor. - */ - TotalVolProductionConstraint( TotalVolProductionConstraint const & ) = delete; - - /** - * @brief Deleted move constructor. - */ - TotalVolProductionConstraint( TotalVolProductionConstraint && ) = delete; - - /** - * @brief Deleted assignment operator. - * @return a reference to a constraint object - */ - TotalVolProductionConstraint & operator=( TotalVolProductionConstraint const & ) = delete; - - /** - * @brief Deleted move operator. - * @return a reference to a constraint object - */ - TotalVolProductionConstraint & operator=( TotalVolProductionConstraint && ) = delete; - - ///@} - - /** - * @name Getters / Setters - */ - ///@{ - /** - * @brief Get name of constraint - * @return constraint key - */ - virtual std::string getConstraintKey( ) const override { return "TotalVolProductionConstraint"; }; - ///@} - - virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const override; -protected: - - virtual void postInputInitialization() override; - -}; - -/** - * @class TotalVolInjectionConstraint - * @brief This class describes a volume rate constraint used to control a injection well. - */ - -class TotalVolInjectionConstraint : public TotalVolConstraint -{ -public: - - - /** - * @name Constructor / Destructor - */ - ///@{ - - /** - * @brief Constructor for TotalVolInjectionConstraint Objects. - * @param[in] name the name of this instantiation of WellControls in the repository - * @param[in] parent the parent group of this instantiation of WellControls - */ - explicit TotalVolInjectionConstraint( string const & name, dataRepository::Group * const parent ); - - - /** - * @brief Default destructor. - */ - ~TotalVolInjectionConstraint() override; - - /** - * @brief Deleted default constructor. - */ - TotalVolInjectionConstraint() = delete; - - /** - * @brief Deleted copy constructor. - */ - TotalVolInjectionConstraint( TotalVolInjectionConstraint const & ) = delete; - - /** - * @brief Deleted move constructor. - */ - TotalVolInjectionConstraint( TotalVolInjectionConstraint && ) = delete; - - /** - * @brief Deleted assignment operator. - * @return a reference to a constraint object - */ - TotalVolInjectionConstraint & operator=( TotalVolInjectionConstraint const & ) = delete; - - /** - * @brief Deleted move operator. - * @return a reference to a constraint object - */ - TotalVolInjectionConstraint & operator=( TotalVolInjectionConstraint && ) = delete; - ///@} - /** - * @name Getters / Setters - */ - ///@{ - - - ///@} - - // Injection stream definition keys - constraintViewStruct::injectionStreamKey viewKeysInjectionStream; - virtual bool checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const override; protected: virtual void postInputInitialization() override; -private: - - /// Vector with global component fractions at the injector - array1d< real64 > m_injectionStream; - - /// Temperature at the injector - real64 m_injectionTemperature; - }; - } //namespace geos #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINT_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp index 03f902dbda2..e90e9efef66 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp @@ -650,7 +650,7 @@ RateInitializationKernel:: ConstraintTypeId const controlType = constraints[0]->getControl(); if( controlType == ConstraintTypeId::PHASEVOLRATE ) { - integer const targetPhaseIndex = dynamic_cast< const PhaseConstraint1< ProductionConstraint > * >( constraints[0] )->getPhaseIndex(); + integer const targetPhaseIndex = dynamic_cast< const PhaseConstraint< ProductionConstraint > * >( constraints[0] )->getPhaseIndex(); forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) { @@ -680,7 +680,7 @@ RateInitializationKernel:: ConstraintTypeId const controlType = constraints[0]->getControl(); if( controlType == ConstraintTypeId::PHASEVOLRATE ) { - integer const targetPhaseIndex = dynamic_cast< const PhaseConstraint1< InjectionConstraint > * >( constraints[0] )->getPhaseIndex(); + integer const targetPhaseIndex = dynamic_cast< const PhaseConstraint< InjectionConstraint > * >( constraints[0] )->getPhaseIndex(); forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp index bf60e40ffe9..30396264de5 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp @@ -529,7 +529,7 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa m_targetBHP = wellControls.getMinBHPConstraint()->getConstraintValue( time ); if( m_currentControl == WellControls::Control::PHASEVOLRATE ) { - m_targetPhaseIndex = dynamic_cast< const PhaseConstraint1< ProductionConstraint > * >( wellControls.getCurrentConstraint() )->getPhaseIndex(); + m_targetPhaseIndex = dynamic_cast< const PhaseConstraint< ProductionConstraint > * >( wellControls.getCurrentConstraint() )->getPhaseIndex(); } } else @@ -537,7 +537,7 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa m_targetBHP = wellControls.getMaxBHPConstraint()->getConstraintValue( time ); if( m_currentControl == WellControls::Control::PHASEVOLRATE ) { - m_targetPhaseIndex = dynamic_cast< const PhaseConstraint1< InjectionConstraint > * >( wellControls.getCurrentConstraint() )->getPhaseIndex(); + m_targetPhaseIndex = dynamic_cast< const PhaseConstraint< InjectionConstraint > * >( wellControls.getCurrentConstraint() )->getPhaseIndex(); } } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellConstraintKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellConstraintKernels.hpp new file mode 100644 index 00000000000..b6876111ca0 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellConstraintKernels.hpp @@ -0,0 +1,196 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file SinglePhaseWellConstraintKernels.hpp + */ + +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_SINGLEPHASEWELLCONSTRAINTKERNELS_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_SINGLEPHASEWELLCONSTRAINTKERNELS_HPP + +#include "codingUtilities/Utilities.hpp" +#include "constitutive/fluid/singlefluid/SingleFluidBase.hpp" +#include "constitutive/fluid/singlefluid/SingleFluidFields.hpp" + + +#include "physicsSolvers/fluidFlow/wells/WellControls.hpp" +#include "physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp" +namespace geos +{ + +namespace singlePhaseWellConstraintKernels +{ + +/******************************** ControlEquationHelper ********************************/ + + +template< integer IS_THERMAL > +struct ConstraintHelper +{ + static void assembleConstraintEquation( real64 const & time_n, + WellControls & wellControls, + BHPConstraint & constraint, + WellElementSubRegion const & subRegion, + string const & wellDofKey, + localIndex const & rankOffset, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) + { + // subRegion data + localIndex const iwelemRef = subRegion.getTopWellElementIndex(); + arrayView1d< globalIndex const > const & wellElemDofNumber = subRegion.getReference< array1d< globalIndex > >( wellDofKey ); + arrayView1d< real64 const > const & pres = subRegion.getField< fields::well::pressure >(); + + constitutive::SingleFluidBase & fluidSeparator = wellControls.getSingleFluidSeparator(); + arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > const & density = fluidSeparator.density(); + arrayView3d< real64 const, constitutive::singlefluid::USD_FLUID_DER > const & dDensity = fluidSeparator.dDensity(); + + arrayView1d< real64 const > const wellElemGravCoef = subRegion.getField< fields::well::gravityCoefficient >(); + + // setup row/column indices for constraint equation + using ROFFSET_WJ = singlePhaseWellKernels::RowOffset_WellJac< IS_THERMAL >; + using COFFSET_WJ = singlePhaseWellKernels::ColOffset_WellJac< IS_THERMAL >; + using Deriv = constitutive::singlefluid::DerivativeOffsetC< IS_THERMAL >; + + localIndex const eqnRowIndex = wellElemDofNumber[iwelemRef] + ROFFSET_WJ::CONTROL - rankOffset; + globalIndex dofColIndices[COFFSET_WJ::nDer]{}; + for( integer i = 0; i < COFFSET_WJ::nDer; ++i ) + { + dofColIndices[ i ] = wellElemDofNumber[iwelemRef] + i; + } + // constraint data + real64 const & targetBHP = constraint.getConstraintValue( time_n ); + real64 const & refGravCoef = constraint.getReferenceGravityCoef(); + + // current constraint value + real64 const & currentBHP = + wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentBHPString() ); + + // residual + real64 controlEqn = currentBHP - targetBHP; + + // setup Jacobian terms + real64 dControlEqn[2+IS_THERMAL]{}; + + // bring everything back to host, capture the scalars by reference + forAll< serialPolicy >( 1, [pres, + density, + dDensity, + wellElemGravCoef, + &dControlEqn, + &iwelemRef, + &refGravCoef] ( localIndex const ) + { + real64 const diffGravCoef = refGravCoef - wellElemGravCoef[iwelemRef]; + dControlEqn[COFFSET_WJ::dP] = 1.0 + dDensity[iwelemRef][0][Deriv::dP] *diffGravCoef; + if constexpr ( IS_THERMAL ) + { + dControlEqn[COFFSET_WJ::dT] = dDensity[iwelemRef][0][Deriv::dT] * diffGravCoef; + } + } ); + + // add solver matrices + localRhs[eqnRowIndex] += controlEqn; + localMatrix.addToRowBinarySearchUnsorted< serialAtomic >( eqnRowIndex, + dofColIndices, + dControlEqn, + COFFSET_WJ::nDer ); + } + template< typename T > + static void assembleConstraintEquation( real64 const & time_n, + WellControls & wellControls, + TotalVolConstraint< T > & constraint, + WellElementSubRegion const & subRegion, + string const & wellDofKey, + localIndex const & rankOffset, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) + { + // subRegion data + + localIndex const iwelemRef = subRegion.getTopWellElementIndex(); + arrayView1d< globalIndex const > const & wellElemDofNumber = subRegion.getReference< array1d< globalIndex > >( wellDofKey ); + + + // setup row/column indices for constraint equation + using ROFFSET_WJ = singlePhaseWellKernels::RowOffset_WellJac< IS_THERMAL >; + using COFFSET_WJ = singlePhaseWellKernels::ColOffset_WellJac< IS_THERMAL >; + using Deriv = constitutive::singlefluid::DerivativeOffsetC< IS_THERMAL >; + + localIndex const eqnRowIndex = wellElemDofNumber[iwelemRef] + ROFFSET_WJ::CONTROL - rankOffset; + globalIndex dofColIndices[COFFSET_WJ::nDer]{}; + for( integer i = 0; i < COFFSET_WJ::nDer; ++i ) + { + dofColIndices[ i ] = wellElemDofNumber[iwelemRef] + i; + } + + // fluid data + constitutive::SingleFluidBase & fluidSeparator = wellControls.getSingleFluidSeparator(); + arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > const & density = fluidSeparator.density(); + arrayView3d< real64 const, constitutive::singlefluid::USD_FLUID_DER > const & dDensity = fluidSeparator.dDensity(); + + // constraint data + real64 const & targetVolRate = constraint.getConstraintValue( time_n ); + + // current constraint value + real64 & currentVolRate = + wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentVolRateString() ); + + integer const useSurfaceConditions = wellControls.useSurfaceConditions(); + + // residual + real64 controlEqn = currentVolRate - targetVolRate; + + // setup Jacobian terms + real64 dControlEqn[2+IS_THERMAL]{}; + + // bring everything back to host, capture the scalars by reference + forAll< serialPolicy >( 1, [currentVolRate, + density, + dDensity, + &dControlEqn, + &useSurfaceConditions, + &iwelemRef] ( localIndex const ) + { + // compute the inverse of the total density and derivatives + real64 const densInv = 1.0 / density[iwelemRef][0]; + + dControlEqn[COFFSET_WJ::dP] = -( useSurfaceConditions == 0 ) * dDensity[iwelemRef][0][Deriv::dP] * currentVolRate * densInv; + dControlEqn[COFFSET_WJ::dQ] = densInv; + if constexpr ( IS_THERMAL ) + { + dControlEqn[COFFSET_WJ::dT] = -( useSurfaceConditions == 0 ) * dDensity[iwelemRef][0][Deriv::dT] * currentVolRate * densInv; + } + + } ); + + // add solver matrices + localRhs[eqnRowIndex] += controlEqn; + localMatrix.addToRowBinarySearchUnsorted< serialAtomic >( eqnRowIndex, + dofColIndices, + dControlEqn, + COFFSET_WJ::nDer ); + } +}; + +} // end namespace wellConstraintKernels + +} // end namespace geos + +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINTKERNELS_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.cpp index b0e87ffbc63..ebd6ee4c657 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.cpp @@ -262,14 +262,10 @@ FluxKernel:: #define INST_PressureRelationKernel( IS_THERMAL ) \ template \ - localIndex \ + void \ PressureRelationKernel:: \ launch< IS_THERMAL >( localIndex const size, \ globalIndex const rankOffset, \ - bool const isLocallyOwned, \ - localIndex const iwelemControl, \ - WellControls const & wellControls, \ - real64 const & timeAtEndOfStep, \ arrayView1d< globalIndex const > const & wellElemDofNumber, \ arrayView1d< real64 const > const & wellElemGravCoef, \ arrayView1d< localIndex const > const & nextWellElemIndex, \ @@ -283,14 +279,10 @@ INST_PressureRelationKernel( 0 ); INST_PressureRelationKernel( 1 ); template< integer IS_THERMAL > -localIndex +void PressureRelationKernel:: launch( localIndex const size, globalIndex const rankOffset, - bool const isLocallyOwned, - localIndex const iwelemControl, - WellControls const & wellControls, - real64 const & time, arrayView1d< globalIndex const > const & wellElemDofNumber, arrayView1d< real64 const > const & wellElemGravCoef, arrayView1d< localIndex const > const & nextWellElemIndex, @@ -303,23 +295,6 @@ PressureRelationKernel:: using Deriv = constitutive::singlefluid::DerivativeOffset; using COFFSET_WJ = singlePhaseWellKernels::ColOffset_WellJac< IS_THERMAL >; // static well control data - bool const isProducer = wellControls.isProducer(); - WellControls::Control const currentControl = wellControls.getControl(); - real64 const targetBHP = wellControls.getTargetBHP( time ); - real64 const targetRate = wellControls.getTargetTotalRate( time ); - - // dynamic well control data - real64 const & currentBHP = - wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentBHPString() ); - arrayView1d< real64 const > const & dCurrentBHP = - wellControls.getReference< array1d< real64 > >( SinglePhaseWell::viewKeyStruct::dCurrentBHPString() ); - - real64 const & currentVolRate = - wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentVolRateString() ); - arrayView1d< real64 const > const & dCurrentVolRate = - wellControls.getReference< array1d< real64 > >( SinglePhaseWell::viewKeyStruct::dCurrentVolRateString() ); - - RAJA::ReduceMax< parallelDeviceReduce, localIndex > switchControl( 0 ); // loop over the well elements to compute the pressure relations between well elements forAll< parallelDevicePolicy<> >( size, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) @@ -327,34 +302,7 @@ PressureRelationKernel:: localIndex const iwelemNext = nextWellElemIndex[iwelem]; - if( iwelemNext < 0 && isLocallyOwned ) // if iwelemNext < 0, form control equation - { - WellControls::Control newControl = currentControl; - ControlEquationHelper::switchControl( isProducer, - currentControl, - targetBHP, - targetRate, - currentBHP, - currentVolRate, - newControl ); - if( currentControl != newControl ) - { - switchControl.max( 1 ); - } - - ControlEquationHelper::compute< IS_THERMAL >( rankOffset, - newControl, - targetBHP, - targetRate, - currentBHP, - dCurrentBHP, - currentVolRate, - dCurrentVolRate, - wellElemDofNumber[iwelemControl], - localMatrix, - localRhs ); - } - else if( iwelemNext >= 0 ) // if iwelemNext >= 0, form momentum equation + if( iwelemNext >= 0 ) // if iwelemNext >= 0, form momentum equation { // local working variables and arrays @@ -406,7 +354,6 @@ PressureRelationKernel:: } } } ); - return switchControl.get(); } /******************************** AccumulationKernel ********************************/ @@ -599,10 +546,22 @@ RateInitializationKernel:: arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > const & wellElemDens, arrayView1d< real64 > const & connRate ) { - real64 const targetRate = wellControls.getTargetTotalRate( currentTime ); + WellControls::Control const control = wellControls.getControl(); bool const isProducer = wellControls.isProducer(); - + real64 constraintVal; + if( isProducer ) + { + std::vector< WellConstraintBase * > const constraints = wellControls.getProdRateConstraints(); + // Use first rate constraint to set initial connection rates + constraintVal = constraints[0]->getConstraintValue( currentTime ); + } + else + { + std::vector< WellConstraintBase * > const constraints = wellControls.getInjRateConstraints(); + // Use first rate constraint to set initial connection rates + constraintVal = constraints[0]->getConstraintValue( currentTime );; + } // Estimate the connection rates forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) { @@ -612,16 +571,16 @@ RateInitializationKernel:: // with the appropriate sign (negative for prod, positive for inj) if( isProducer ) { - connRate[iwelem] = LvArray::math::max( 0.1 * targetRate * wellElemDens[iwelem][0], -1e3 ); + connRate[iwelem] = LvArray::math::max( 0.1 * constraintVal * wellElemDens[iwelem][0], -1e3 ); } else { - connRate[iwelem] = LvArray::math::min( 0.1 * targetRate * wellElemDens[iwelem][0], 1e3 ); + connRate[iwelem] = LvArray::math::min( 0.1 * constraintVal * wellElemDens[iwelem][0], 1e3 ); } } else { - connRate[iwelem] = targetRate * wellElemDens[iwelem][0]; + connRate[iwelem] = constraintVal * wellElemDens[iwelem][0]; } } ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.hpp index 5221162c73c..80a471e22d9 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.hpp @@ -185,13 +185,9 @@ struct PressureRelationKernel using TAG = singlePhaseWellKernels::ElemTag; template< integer IS_THERMAL > - static localIndex + static void launch( localIndex const size, globalIndex const rankOffset, - bool const isLocallyOwned, - localIndex const iwelemControl, - WellControls const & wellControls, - real64 const & time, arrayView1d< globalIndex const > const & wellElemDofNumber, arrayView1d< real64 const > const & wellElemGravCoef, arrayView1d< localIndex const > const & nextWellElemIndex, @@ -811,12 +807,19 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa m_isLocallyOwned( subRegion.isLocallyOwned() ), m_iwelemControl( subRegion.getTopWellElementIndex() ), m_currentControl( wellControls.getControl() ), - m_targetBHP( wellControls.getTargetBHP( time ) ), - m_targetRate( wellControls.getTargetTotalRate( time ) ), - m_targetMassRate( wellControls.getTargetMassRate( time ) ), + m_constraintValue ( wellControls.getCurrentConstraint()->getConstraintValue( time )), m_volume( subRegion.getElementVolume() ), m_density_n( fluid.density_n() ) - {} + { + if( wellControls.isProducer() ) + { + m_targetBHP = wellControls.getMinBHPConstraint()->getConstraintValue( time ); + } + else + { + m_targetBHP = wellControls.getMaxBHPConstraint()->getConstraintValue( time ); + } + } GEOS_HOST_DEVICE virtual void computeLinf( localIndex const iwelem, @@ -838,12 +841,12 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa else if( m_currentControl == WellControls::Control::TOTALVOLRATE ) { // this residual entry is in volume / time units - normalizer = LvArray::math::max( LvArray::math::abs( m_targetRate ), m_minNormalizer ); + normalizer = LvArray::math::max( LvArray::math::abs( m_constraintValue ), m_minNormalizer ); } else if( m_currentControl == WellControls::Control::MASSRATE ) { // the residual entry is in volume / time units - normalizer = LvArray::math::max( LvArray::math::abs( m_targetMassRate ), m_minNormalizer ); + normalizer = LvArray::math::max( LvArray::math::abs( m_constraintValue ), m_minNormalizer ); } } // for the pressure difference equation, always normalize by the BHP @@ -856,7 +859,7 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa else // SinglePhaseWell::RowOffset::MASSBAL { // this residual entry is in mass units - normalizer = m_dt * LvArray::math::abs( m_targetRate ) * m_density_n[iwelem][0]; + normalizer = m_dt * LvArray::math::abs( m_constraintValue ) * m_density_n[iwelem][0]; // to make sure that everything still works well if the rate is zero, we add this check normalizer = LvArray::math::max( normalizer, m_volume[iwelem] * m_density_n[iwelem][0] ); @@ -894,9 +897,9 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa /// Controls WellControls::Control const m_currentControl; - real64 const m_targetBHP; - real64 const m_targetRate; - real64 const m_targetMassRate; + real64 const m_constraintValue; + real64 m_targetBHP; + /// View on the volume arrayView1d< real64 const > const m_volume; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp index f27176b4872..cf192b1e8aa 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp @@ -191,15 +191,20 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa if( m_isProducer ) { m_targetBHP = wellControls.getMinBHPConstraint()->getConstraintValue( time ); + if( m_currentControl == WellControls::Control::PHASEVOLRATE ) + { + m_targetPhaseIndex = dynamic_cast< const PhaseConstraint< ProductionConstraint > * >( wellControls.getCurrentConstraint() )->getPhaseIndex(); + } } else { m_targetBHP = wellControls.getMaxBHPConstraint()->getConstraintValue( time ); + if( m_currentControl == WellControls::Control::PHASEVOLRATE ) + { + m_targetPhaseIndex = dynamic_cast< const PhaseConstraint< InjectionConstraint > * >( wellControls.getCurrentConstraint() )->getPhaseIndex(); + } } - if( m_currentControl == WellControls::Control::PHASEVOLRATE ) - { - m_targetPhaseIndex = dynamic_cast< const PhaseConstraint * >( wellControls.getCurrentConstraint() )->getPhaseIndex(); - } + } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalSinglePhaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalSinglePhaseWellKernels.hpp index f736826561c..b19ca90845d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalSinglePhaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalSinglePhaseWellKernels.hpp @@ -522,14 +522,21 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa m_iwelemControl( subRegion.getTopWellElementIndex() ), m_isProducer( wellControls.isProducer() ), m_currentControl( wellControls.getControl() ), - m_targetBHP( wellControls.getTargetBHP( time ) ), - m_targetRate( wellControls.getTargetTotalRate( time ) ), - m_targetMassRate( wellControls.getTargetMassRate( time ) ), + m_constraintValue ( wellControls.getCurrentConstraint()->getConstraintValue( time )), m_volume( subRegion.getElementVolume() ), m_density_n( fluid.density_n() ), m_internalEnergy_n( fluid.internalEnergy_n() ) - {} + { + if( wellControls.isProducer() ) + { + m_targetBHP = wellControls.getMinBHPConstraint()->getConstraintValue( time ); + } + else + { + m_targetBHP = wellControls.getMaxBHPConstraint()->getConstraintValue( time ); + } + } GEOS_HOST_DEVICE @@ -568,12 +575,12 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa else if( m_currentControl == WellControls::Control::TOTALVOLRATE ) { // the residual entry is in volume / time units - normalizer = LvArray::math::max( LvArray::math::abs( m_targetRate ), m_minNormalizer ); + normalizer = LvArray::math::max( LvArray::math::abs( m_constraintValue ), m_minNormalizer ); } else if( m_currentControl == WellControls::Control::MASSRATE ) { // the residual entry is in volume / time units - normalizer = LvArray::math::max( LvArray::math::abs( m_targetMassRate ), m_minNormalizer ); + normalizer = LvArray::math::max( LvArray::math::abs( m_constraintValue ), m_minNormalizer ); } } // for the pressure difference equation, always normalize by the BHP @@ -587,7 +594,7 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa { // this residual entry is in mass units - normalizer = m_dt * LvArray::math::abs( m_targetRate ) * m_density_n[iwelem][0]; + normalizer = m_dt * LvArray::math::abs( m_constraintValue ) * m_density_n[iwelem][0]; // to make sure that everything still works well if the rate is zero, we add this check normalizer = LvArray::math::max( normalizer, m_volume[iwelem] * m_density_n[iwelem][0] ); @@ -640,9 +647,8 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa /// Controls WellControls::Control const m_currentControl; - real64 const m_targetBHP; - real64 const m_targetRate; - real64 const m_targetMassRate; + real64 const m_constraintValue; + real64 m_targetBHP; /// View on the volume arrayView1d< real64 const > const m_volume; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/WellConstraintKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/WellConstraintKernels.hpp index a99691e8d68..f9a19cba38b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/WellConstraintKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/WellConstraintKernels.hpp @@ -38,11 +38,11 @@ namespace wellConstraintKernels { /******************************** ControlEquationHelper ********************************/ -template< integer NC, integer IS_THERMAL, typename T > -struct ConstraintHelper {}; +//template< integer NC, integer IS_THERMAL, typname S, typename T > +//struct ConstraintHelper< NC, IS_THERMAL > {}; -template< integer NC, integer IS_THERMAL > -struct ConstraintHelper< NC, IS_THERMAL, BHPConstraint > +template< integer NC, integer IS_THERMAL, typename CONSTRAINT = BHPConstraint > +struct ConstraintHelper { static void assembleConstraintEquation( real64 const & time_n, WellControls & wellControls, @@ -115,14 +115,12 @@ struct ConstraintHelper< NC, IS_THERMAL, BHPConstraint > dControlEqn, COFFSET_WJ::nDer ); } -}; -template< integer NC, integer IS_THERMAL > -struct ConstraintHelper< NC, IS_THERMAL, PhaseConstraint > -{ + + template< typename T > static void assembleConstraintEquation( real64 const & time_n, WellControls & wellControls, - PhaseConstraint & constraint, + PhaseConstraint< T > & constraint, WellElementSubRegion const & subRegion, string const & wellDofKey, localIndex const & rankOffset, @@ -225,14 +223,11 @@ struct ConstraintHelper< NC, IS_THERMAL, PhaseConstraint > dControlEqn, COFFSET_WJ::nDer ); } -}; -template< integer NC, integer IS_THERMAL > -struct ConstraintHelper< NC, IS_THERMAL, LiquidConstraint > -{ + template< typename T > static void assembleConstraintEquation( real64 const & time_n, WellControls & wellControls, - LiquidConstraint & constraint, + LiquidConstraint< T > & constraint, WellElementSubRegion const & subRegion, string const & wellDofKey, localIndex const & rankOffset, @@ -346,14 +341,10 @@ struct ConstraintHelper< NC, IS_THERMAL, LiquidConstraint > dControlEqn, COFFSET_WJ::nDer ); } -}; - -template< integer NC, integer IS_THERMAL > -struct ConstraintHelper< NC, IS_THERMAL, TotalVolConstraint > -{ + template< typename T > static void assembleConstraintEquation( real64 const & time_n, WellControls & wellControls, - TotalVolConstraint & constraint, + TotalVolConstraint< T > & constraint, WellElementSubRegion const & subRegion, string const & wellDofKey, localIndex const & rankOffset, @@ -450,14 +441,10 @@ struct ConstraintHelper< NC, IS_THERMAL, TotalVolConstraint > dControlEqn, COFFSET_WJ::nDer ); } -}; - -template< integer NC, integer IS_THERMAL > -struct ConstraintHelper< NC, IS_THERMAL, MassConstraint > -{ + template< typename T > static void assembleConstraintEquation( real64 const & time_n, WellControls & wellControls, - MassConstraint & constraint, + MassConstraint< T > & constraint, WellElementSubRegion const & subRegion, string const & wellDofKey, localIndex const & rankOffset, From 4f49bf107a4c37b7ed1a20c3ceaaba35bea99eb9 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 7 Oct 2025 16:18:59 -0700 Subject: [PATCH 07/71] fix constraint sign and normalizers --- .../fluidFlow/wells/WellConstraintsBase.cpp | 9 +++++-- .../fluidFlow/wells/WellControls.hpp | 1 + .../CompositionalMultiphaseWellKernels.hpp | 26 ++++++++++++------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp index f3bbfc1e129..a0279fbce09 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp @@ -144,10 +144,13 @@ void WellConstraintBase::setNextDtFromTable( TableFunction const * table, real64 } } -// *** Phase Constraint for Injection Well *************************************************************** +// *** Phase Constraint for Production Well *************************************************************** ProductionConstraint::ProductionConstraint( string const & name, Group * const parent ) : WellConstraintBase( name, parent ) -{} +{ + // set rate sign for producers (base class member) + m_rateSign = -1.0; +} ProductionConstraint::~ProductionConstraint() {} @@ -163,6 +166,8 @@ void ProductionConstraint::postInputInitialization() InjectionConstraint::InjectionConstraint( string const & name, Group * const parent ) : WellConstraintBase( name, parent ) { + // set rate sign for injectors (base class member) + m_rateSign = 1.0; registerWrapper( injectionStreamKey::injectionStreamString(), &m_injectionStream ). setDefaultValue( -1 ). setSizedFromParent( 0 ). diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp index 5421d7c7e7f..1c5b04e2459 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp @@ -228,6 +228,7 @@ class WellControls : public dataRepository::Group } return getMaxBHPConstraint()->getReferenceElevation(); } + /** * @brief Getter for the flag specifying whether we check rates at surface or reservoir conditions * @return 1 if we use surface conditions, and 0 otherwise diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp index 30396264de5..30fc875f85c 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp @@ -519,7 +519,6 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa m_iwelemControl( subRegion.getTopWellElementIndex() ), m_isProducer( wellControls.isProducer() ), m_currentControl( wellControls.getControl() ), - m_constraintValue ( wellControls.getCurrentConstraint()->getConstraintValue( time )), m_volume( subRegion.getElementVolume() ), m_phaseDens_n( fluid.phaseDensity_n() ), m_totalDens_n( fluid.totalDensity_n() ) @@ -527,18 +526,25 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa if( m_isProducer ) { m_targetBHP = wellControls.getMinBHPConstraint()->getConstraintValue( time ); - if( m_currentControl == WellControls::Control::PHASEVOLRATE ) - { - m_targetPhaseIndex = dynamic_cast< const PhaseConstraint< ProductionConstraint > * >( wellControls.getCurrentConstraint() )->getPhaseIndex(); - } + // Note this assumes that there is only one rate constraint + // This is a normalizer for the balance equations. The normalizaer should be the current rate not the constraint value!! + // This is one of the reasons for restricting constraint type for a production well + // another pr will remove fix this (so the cause for difference results is isolated to one change) + m_targetPhaseIndex = dynamic_cast< PhaseConstraint< ProductionConstraint > * >(wellControls.getProdRateConstraints()[0])->getPhaseIndex( ); + m_constraintValue = wellControls.getProdRateConstraints()[0]->getConstraintValue( time ); + } else { m_targetBHP = wellControls.getMaxBHPConstraint()->getConstraintValue( time ); - if( m_currentControl == WellControls::Control::PHASEVOLRATE ) - { - m_targetPhaseIndex = dynamic_cast< const PhaseConstraint< InjectionConstraint > * >( wellControls.getCurrentConstraint() )->getPhaseIndex(); - } + + // Note this assumes that there is only one rate constraint + // This is a normalizer for the balance equations. The normalizaer should be the current rate not the constraint value!! + // This is one of the reasons for restricting constraint type for a production well + // another pr will remove fix this (so the cause for difference results is isolated to one change) + m_targetPhaseIndex = -1; + m_constraintValue = wellControls.getInjRateConstraints()[0]->getConstraintValue( time ); + } @@ -684,7 +690,7 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa /// Controls WellControls::Control const m_currentControl; - real64 const m_constraintValue; + real64 m_constraintValue; real64 m_targetBHP; From 2e82b49f7eb99de63354fcb87c9c4fad69a172fd Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Wed, 8 Oct 2025 09:54:19 -0700 Subject: [PATCH 08/71] 1) compositional_multiphase_wells_1d.xml matches geos branch, 2) singlephase still needs testing --- .../wells/CompositionalMultiphaseWell.cpp | 72 +++++++++---------- .../CompositionalMultiphaseWellKernels.cpp | 2 +- 2 files changed, 33 insertions(+), 41 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 758df943552..669f93f748a 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -1231,6 +1231,29 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh m_nextDt=43200; } wellControls.setWellState( true ); + if( wellControls.getCurrentConstraint() == nullptr ) + { + if( wellControls.isProducer() ) + { + wellControls.forSubGroups< MinimumBHPConstraint >( [&]( auto & constraint ) + //wellControls.forSubGroups< PhaseProductionConstraint >( [&]( auto & constraint + // ) + { + wellControls.setCurrentConstraint( &constraint ); + wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old + } ); + } + else + { + // tjb needed for backward compatibility + //wellControls.forSubGroups< MaximumBHPConstraint >( [&]( auto & constraint ) + wellControls.forSubGroups< TotalVolConstraint< InjectionConstraint > >( [&]( auto & constraint ) + { + wellControls.setCurrentConstraint( &constraint ); + wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old + } ); + } + } // get well primary variables on well elements arrayView1d< real64 > const & wellElemPressure = subRegion.getField< well::pressure >(); arrayView1d< real64 > const & wellElemTemp = subRegion.getField< well::temperature >(); @@ -1317,7 +1340,14 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh connRate ); updateVolRatesForConstraint( subRegion ); - + // Since this is a well manager class the rates need to be pushed into the WellControls class, which represnets the well + WellConstraintBase * constraint = wellControls.getCurrentConstraint(); + constraint->setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); + constraint->setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( + CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); + constraint->setTotalVolumeRate ( wellControls.getReference< real64 >( + CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); + constraint->setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); // 7) Copy well / fluid dofs to "prop"_n variables saveState( subRegion ); } @@ -1329,45 +1359,7 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh else { wellControls.setWellState( true ); - } - // Initialize well with pressure constraint - if( wellControls.getWellState( ) ) - { - if( wellControls.getCurrentConstraint() == nullptr ) - { - if( wellControls.isProducer() ) - { - wellControls.forSubGroups< MinimumBHPConstraint >( [&]( auto & constraint ) - //wellControls.forSubGroups< PhaseProductionConstraint >( [&]( auto & constraint - // ) - { - constraint.setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); - constraint.setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( - CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); - constraint.setTotalVolumeRate ( wellControls.getReference< real64 >( - CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); - constraint.setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); - wellControls.setCurrentConstraint( &constraint ); - wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old - } ); - } - else - { - // tjb needed for backward compatibility - //wellControls.forSubGroups< MaximumBHPConstraint >( [&]( auto & constraint ) - wellControls.forSubGroups< TotalVolConstraint< InjectionConstraint > >( [&]( auto & constraint ) - { - constraint.setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); - constraint.setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( - CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); - constraint.setTotalVolumeRate ( wellControls.getReference< real64 >( - CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); - constraint.setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); - wellControls.setCurrentConstraint( &constraint ); - wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old - } ); - } - } + } } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp index e90e9efef66..962562d26f6 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp @@ -691,7 +691,7 @@ RateInitializationKernel:: { forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) { - connRate[iwelem] = LvArray::math::max( 0.1 * constraintVal * totalDens[iwelem][0], 1e3 ); + connRate[iwelem] = constraintVal * totalDens[iwelem][0]; } ); } else if( controlType == ConstraintTypeId::MASSRATE ) From 6281018216bc3641759294ae4996a25a4ae93fbe Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Thu, 9 Oct 2025 14:25:50 -0700 Subject: [PATCH 09/71] compressible_single_phase_wells_1d.xml matches geos branch --- .../wells/CompositionalMultiphaseWell.cpp | 276 +++-------- .../fluidFlow/wells/SinglePhaseWell.cpp | 433 +++++++++++++----- .../fluidFlow/wells/SinglePhaseWell.hpp | 19 +- .../fluidFlow/wells/WellSolverBase.hpp | 4 +- 4 files changed, 419 insertions(+), 313 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 669f93f748a..6eff710a626 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -608,8 +608,7 @@ void CompositionalMultiphaseWell::updateVolRatesForConstraint( WellElementSubReg return; } - integer constexpr maxNumComp = constitutive::MultiFluidBase::MAX_NUM_COMPONENTS; - integer const numComp = m_numComponents; + integer const numPhase = m_numPhases; localIndex const iwelemRef = subRegion.getTopWellElementIndex(); @@ -617,60 +616,21 @@ void CompositionalMultiphaseWell::updateVolRatesForConstraint( WellElementSubReg // subRegion data - arrayView1d< real64 const > const & pres = subRegion.getField< well::pressure >(); - arrayView1d< real64 const > const & temp = subRegion.getField< well::temperature >(); arrayView1d< real64 const > const & connRate = subRegion.getField< well::mixtureConnectionRate >(); - arrayView2d< real64 const, compflow::USD_COMP > const & compFrac = subRegion.getField< well::globalCompFraction >(); - arrayView3d< real64 const, compflow::USD_COMP_DC > const & dCompFrac_dCompDens = subRegion.getField< well::dGlobalCompFraction_dGlobalCompDensity >(); - // fluid data constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); - integer isThermal = fluidSeparator.isThermal(); - arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const & phaseFrac = fluidSeparator.phaseFraction(); - arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > const & dPhaseFrac = fluidSeparator.dPhaseFraction(); + arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const & phaseFrac = fluidSeparator.phaseFraction(); arrayView2d< real64 const, constitutive::multifluid::USD_FLUID > const & totalDens = fluidSeparator.totalDensity(); - arrayView3d< real64 const, constitutive::multifluid::USD_FLUID_DC > const & dTotalDens = fluidSeparator.dTotalDensity(); - arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const & phaseDens = fluidSeparator.phaseDensity(); - arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > const & dPhaseDens = fluidSeparator.dPhaseDensity(); // control data string const wellControlsName = wellControls.getName(); - bool const logSurfaceCondition = isLogLevelActive< logInfo::BoundaryConditions >( wellControls.getLogLevel()); - string const massUnit = m_useMass ? "kg" : "mol"; - integer const useSurfaceConditions = wellControls.useSurfaceConditions(); - real64 flashPressure; - real64 flashTemperature; - if( useSurfaceConditions ) - { - // use surface conditions - flashPressure = wellControls.getSurfacePressure(); - flashTemperature = wellControls.getSurfaceTemperature(); - } - else - { - // If flashPressure is not set by region the value is defaulted to -1 and indicates to use top segment conditions - flashPressure = wellControls.getRegionAveragePressure(); - if( flashPressure < 0.0 ) - { - // region name not set, use segment conditions - flashPressure = pres[iwelemRef]; - flashTemperature = temp[iwelemRef]; - } - else - { - // use reservoir region averages - flashTemperature = wellControls.getRegionAverageTemperature(); - } - } arrayView1d< real64 > const & currentPhaseVolRate = wellControls.getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ); - arrayView2d< real64 > const & dCurrentPhaseVolRate = - wellControls.getReference< array2d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::dCurrentPhaseVolRateString() ); real64 & currentTotalVolRate = wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() ); @@ -678,161 +638,53 @@ void CompositionalMultiphaseWell::updateVolRatesForConstraint( WellElementSubReg real64 & currentMassRate = wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() ); - arrayView1d< real64 > const & dCurrentTotalVolRate = - wellControls.getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::dCurrentTotalVolRateString() ); - real64 & massDensity = wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::massDensityString() ); - constitutive::constitutiveUpdatePassThru( fluidSeparator, [&] ( auto & castedFluidSeparator ) - { - // typename TYPEOFREF( castedFluid ) ::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); - typename TYPEOFREF( castedFluidSeparator ) ::KernelWrapper fluidSeparatorWrapper = castedFluidSeparator.createKernelWrapper(); - geos::internal::kernelLaunchSelectorCompThermSwitch( numComp, isThermal, [&] ( auto NC, auto ISTHERMAL ) - { - integer constexpr NUM_COMP = NC(); - integer constexpr IS_THERMAL = ISTHERMAL(); - using COFFSET_WJ = compositionalMultiphaseWellKernels::ColOffset_WellJac< NUM_COMP, IS_THERMAL >; - // bring everything back to host, capture the scalars by reference - forAll< serialPolicy >( 1, [&numComp, - &numPhase, - fluidSeparatorWrapper, - pres, - temp, - compFrac, - dCompFrac_dCompDens, - connRate, - totalDens, - dTotalDens, - phaseDens, - dPhaseDens, - phaseFrac, - dPhaseFrac, - logSurfaceCondition, - &useSurfaceConditions, - &flashPressure, - &flashTemperature, - ¤tTotalVolRate, - dCurrentTotalVolRate, - currentPhaseVolRate, - dCurrentPhaseVolRate, - ¤tMassRate, - &iwelemRef, - &wellControlsName, - &massUnit, - &massDensity] ( localIndex const ) - { - GEOS_UNUSED_VAR( massUnit ); - using Deriv = constitutive::multifluid::DerivativeOffset; - stackArray1d< real64, maxNumComp > work( numComp ); - // Step 1: evaluate the phase and total density in the reference element - - // We need to evaluate the density as follows: - // - Surface conditions: using the surface pressure provided by the user - // - Segment conditions: using the pressure in the top element - // - Reservoir conditions: using the average region pressure - if( useSurfaceConditions ) - { - // we need to compute the surface density - fluidSeparatorWrapper.update( iwelemRef, 0, flashPressure, flashTemperature, compFrac[iwelemRef] ); - if( logSurfaceCondition ) - { - GEOS_LOG_RANK( GEOS_FMT( "{}: surface density computed with P_surface = {} Pa and T_surface = {} K", - wellControlsName, flashPressure, flashTemperature ) ); - } -#ifdef GEOS_USE_HIP - GEOS_UNUSED_VAR( wellControlsName ); -#endif - - } - else - { - fluidSeparatorWrapper.update( iwelemRef, 0, flashPressure, flashTemperature, compFrac[iwelemRef] ); - } - // 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]; - - stackArray1d< real64, maxNumComp > dTotalDensInv_dCompDens( numComp ); - for( integer ic = 0; ic < numComp; ++ic ) - { - dTotalDensInv_dCompDens[ic] = -dTotalDens[iwelemRef][0][Deriv::dC+ic] * totalDensInv * totalDensInv; - } - applyChainRuleInPlace( numComp, dCompFrac_dCompDens[iwelemRef], dTotalDensInv_dCompDens, work.data() ); - - // Step 2.2: divide the total mass/molar rate by the total density to get the total volumetric rate - currentTotalVolRate = currentTotalRate * totalDensInv; - // Compute derivatives dP dT - real64 const dTotalDensInv_dPres = -dTotalDens[iwelemRef][0][Deriv::dP] * totalDensInv * totalDensInv; - dCurrentTotalVolRate[COFFSET_WJ::dP] = ( useSurfaceConditions == 0 ) * currentTotalRate * dTotalDensInv_dPres; - if constexpr ( IS_THERMAL ) - { - dCurrentTotalVolRate[COFFSET_WJ::dT] = ( useSurfaceConditions == 0 ) * currentTotalRate * -dTotalDens[iwelemRef][0][Deriv::dT] * totalDensInv * totalDensInv; - } - - if( logSurfaceCondition && useSurfaceConditions ) - { - GEOS_LOG_RANK( GEOS_FMT( "{}: total fluid density at surface conditions = {} {}/sm3, total rate = {} {}/s, total surface volumetric rate = {} sm3/s", - wellControlsName, totalDens[iwelemRef][0], massUnit, connRate[iwelemRef], massUnit, currentTotalVolRate ) ); - } - - dCurrentTotalVolRate[COFFSET_WJ::dQ] = totalDensInv; - for( integer ic = 0; ic < numComp; ++ic ) - { - dCurrentTotalVolRate[COFFSET_WJ::dC+ic] = currentTotalRate * dTotalDensInv_dCompDens[ic]; - } - - // Step 3: update the phase volume rate - for( integer ip = 0; ip < numPhase; ++ip ) - { - - // Step 3.1: compute the inverse of the (phase density * phase fraction) and derivatives - - // skip the rest of this function if phase ip is absent - bool const phaseExists = (phaseFrac[iwelemRef][0][ip] > 0); - if( !phaseExists ) - { - continue; - } - - real64 const phaseDensInv = 1.0 / phaseDens[iwelemRef][0][ip]; - real64 const phaseFracTimesPhaseDensInv = phaseFrac[iwelemRef][0][ip] * phaseDensInv; - real64 const dPhaseFracTimesPhaseDensInv_dPres = dPhaseFrac[iwelemRef][0][ip][Deriv::dP] * phaseDensInv - - dPhaseDens[iwelemRef][0][ip][Deriv::dP] * phaseFracTimesPhaseDensInv * phaseDensInv; + // bring everything back to host, capture the scalars by reference + forAll< serialPolicy >( 1, [&numPhase, + connRate, + totalDens, + phaseDens, + phaseFrac, + ¤tTotalVolRate, + currentPhaseVolRate, + ¤tMassRate, + &iwelemRef, + &massDensity] ( localIndex const ) + { + // Step 1: update the total volume rate + + real64 const currentTotalRate = connRate[iwelemRef]; + // Assumes useMass is true + currentMassRate = currentTotalRate; + // Step 1.1: compute the inverse of the total density and derivatives + massDensity = totalDens[iwelemRef][0]; + real64 const totalDensInv = 1.0 / totalDens[iwelemRef][0]; + + // Step 1.2: divide the total mass/molar rate by the total density to get the total volumetric rate + currentTotalVolRate = currentTotalRate * totalDensInv; + + // Step 2: update the phase volume rate + for( integer ip = 0; ip < numPhase; ++ip ) + { + // Step 2.1: compute the inverse of the (phase density * phase fraction) and derivatives - // Step 3.2: divide the total mass/molar rate by the (phase density * phase fraction) to get the phase volumetric rate - currentPhaseVolRate[ip] = currentTotalRate * phaseFracTimesPhaseDensInv; - dCurrentPhaseVolRate[ip][COFFSET_WJ::dP] = ( useSurfaceConditions == 0 ) * currentTotalRate * dPhaseFracTimesPhaseDensInv_dPres; - dCurrentPhaseVolRate[ip][COFFSET_WJ::dQ] = phaseFracTimesPhaseDensInv; - if constexpr (IS_THERMAL ) - { - real64 const dPhaseFracTimesPhaseDensInv_dTemp = dPhaseFrac[iwelemRef][0][ip][Deriv::dT] * phaseDensInv - - dPhaseDens[iwelemRef][0][ip][Deriv::dT] * phaseFracTimesPhaseDensInv * phaseDensInv; - dCurrentPhaseVolRate[ip][COFFSET_WJ::dT] = ( useSurfaceConditions == 0 ) * currentTotalRate * dPhaseFracTimesPhaseDensInv_dTemp; - } + // skip the rest of this function if phase ip is absent + bool const phaseExists = (phaseFrac[iwelemRef][0][ip] > 0); + if( !phaseExists ) + { + continue; + } - for( integer ic = 0; ic < numComp; ++ic ) - { - dCurrentPhaseVolRate[ip][COFFSET_WJ::dC+ic] = -phaseFracTimesPhaseDensInv * dPhaseDens[iwelemRef][0][ip][Deriv::dC+ic] * phaseDensInv; - dCurrentPhaseVolRate[ip][COFFSET_WJ::dC+ic] += dPhaseFrac[iwelemRef][0][ip][Deriv::dC+ic] * phaseDensInv; - dCurrentPhaseVolRate[ip][COFFSET_WJ::dC+ic] *= currentTotalRate; - } - applyChainRuleInPlace( numComp, dCompFrac_dCompDens[iwelemRef], &dCurrentPhaseVolRate[ip][COFFSET_WJ::dC], work.data() ); + real64 const phaseDensInv = 1.0 / phaseDens[iwelemRef][0][ip]; + real64 const phaseFracTimesPhaseDensInv = phaseFrac[iwelemRef][0][ip] * phaseDensInv; - if( logSurfaceCondition && useSurfaceConditions ) - { - GEOS_LOG_RANK( GEOS_FMT( "{}: density of phase {} at surface conditions = {} {}/sm3, phase surface volumetric rate = {} sm3/s", - wellControlsName, ip, phaseDens[iwelemRef][0][ip], massUnit, currentPhaseVolRate[ip] ) ); - } - } - } ); - } ); + // Step 2.2: divide the total mass/molar rate by the (phase density * phase fraction) to get the phase volumetric rate + currentPhaseVolRate[ip] = currentTotalRate * phaseFracTimesPhaseDensInv; + } } ); + } void CompositionalMultiphaseWell::calculateReferenceElementRates( WellElementSubRegion & subRegion ) @@ -1009,8 +861,30 @@ void CompositionalMultiphaseWell::updateSeparator( WellElementSubRegion & subReg string const massUnit = m_useMass ? "kg" : "mol"; integer const useSurfaceConditions = wellControls.useSurfaceConditions(); - real64 const & surfacePres = wellControls.getSurfacePressure(); - real64 const & surfaceTemp = wellControls.getSurfaceTemperature(); + real64 flashPressure; + real64 flashTemperature; + if( useSurfaceConditions ) + { + // use surface conditions + flashPressure = wellControls.getSurfacePressure(); + flashTemperature = wellControls.getSurfaceTemperature(); + } + else + { + // If flashPressure is not set by region the value is defaulted to -1 and indicates to use top segment conditions + flashPressure = wellControls.getRegionAveragePressure(); + if( flashPressure < 0.0 ) + { + // region name not set, use segment conditions + flashPressure = pres[iwelemRef]; + flashTemperature = temp[iwelemRef]; + } + else + { + // use reservoir region averages + flashTemperature = wellControls.getRegionAverageTemperature(); + } + } constitutive::constitutiveUpdatePassThru( fluidSeparator, [&] ( auto & castedFluidSeparator ) { @@ -1020,8 +894,8 @@ void CompositionalMultiphaseWell::updateSeparator( WellElementSubRegion & subReg forAll< serialPolicy >( 1, [fluidSeparatorWrapper, wellControlsName, useSurfaceConditions, - surfacePres, - surfaceTemp, + flashPressure, + flashTemperature, logSurfaceCondition, iwelemRef, pres, @@ -1034,11 +908,11 @@ void CompositionalMultiphaseWell::updateSeparator( WellElementSubRegion & subReg { // we need to compute the surface density //fluidWrapper.update( iwelemRef, 0, surfacePres, surfaceTemp, compFrac[iwelemRef] ); - fluidSeparatorWrapper.update( iwelemRef, 0, surfacePres, surfaceTemp, compFrac[iwelemRef] ); + fluidSeparatorWrapper.update( iwelemRef, 0, flashPressure, flashTemperature, compFrac[iwelemRef] ); if( logSurfaceCondition ) { GEOS_LOG_RANK( GEOS_FMT( "{}: surface density computed with P_surface = {} Pa and T_surface = {} K", - wellControlsName, surfacePres, surfaceTemp ) ); + wellControlsName, flashPressure, flashTemperature ) ); } #ifdef GEOS_USE_HIP GEOS_UNUSED_VAR( wellControlsName ); @@ -1046,8 +920,7 @@ void CompositionalMultiphaseWell::updateSeparator( WellElementSubRegion & subReg } else { - real64 const refPres = pres[iwelemRef]; - fluidSeparatorWrapper.update( iwelemRef, 0, refPres, temp[iwelemRef], compFrac[iwelemRef] ); + fluidSeparatorWrapper.update( iwelemRef, 0, flashPressure, flashTemperature, compFrac[iwelemRef] ); } } ); } ); @@ -1156,17 +1029,14 @@ real64 CompositionalMultiphaseWell::updateSubRegionState( WellElementSubRegion & // update properties updateGlobalComponentFraction( subRegion ); - // update volumetric rates for the well constraints - // note: this must be called before updateFluidModel - - updateVolRatesForConstraint( subRegion ); // remove - // update densities, phase fractions, phase volume fractions updateFluidModel( subRegion ); // Calculate fluid properties updateSeparator( subRegion ); // Calculate fluid properties at control conditions + updateVolRatesForConstraint( subRegion ); // remove tjb ?? + maxPhaseVolChange = updatePhaseVolumeFraction( subRegion ); updateTotalMassDensity( subRegion ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index 7d5b80c6058..4313497a0ad 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -199,6 +199,36 @@ void SinglePhaseWell::validateWellConstraints( real64 const & time_n, #endif } +void SinglePhaseWell::initializePostInitialConditionsPreSubGroups() +{ + WellSolverBase::initializePostInitialConditionsPreSubGroups(); + createSeparator(); +} +void SinglePhaseWell::createSeparator() +{ + DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + + // loop over the wells + mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + SingleFluidBase & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); + // setup fluid separator + WellControls & wellControls = getWellControls( subRegion ); + string const fluidSeparatorName = wellControls.getName() + "Separator"; + std::unique_ptr< constitutive::ConstitutiveBase > fluidSeparatorPtr = fluid.deliverClone( fluidSeparatorName, &wellControls ); + fluidSeparatorPtr->allocateConstitutiveData( wellControls, 1 ); + fluidSeparatorPtr->resize( 1 ); + wellControls.setFluidSeparator( std::move( fluidSeparatorPtr )); + } ); + } ); +} + void SinglePhaseWell::updateBHPForConstraint( WellElementSubRegion & subRegion ) { GEOS_MARK_FUNCTION; @@ -266,7 +296,7 @@ void SinglePhaseWell::updateBHPForConstraint( WellElementSubRegion & subRegion ) } -void SinglePhaseWell::updateVolRateForConstraint( WellElementSubRegion & subRegion ) +void SinglePhaseWell::calculateReferenceElementRates( WellElementSubRegion & subRegion ) { GEOS_MARK_FUNCTION; @@ -280,9 +310,6 @@ void SinglePhaseWell::updateVolRateForConstraint( WellElementSubRegion & subRegi // subRegion data - arrayView1d< real64 const > const pres = - subRegion.getField< well::pressure >(); - arrayView1d< real64 const > const & connRate = subRegion.getField< well::connectionRate >(); @@ -291,14 +318,71 @@ void SinglePhaseWell::updateVolRateForConstraint( WellElementSubRegion & subRegi string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); SingleFluidBase & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > const & dens = fluid.density(); - arrayView3d< real64 const, constitutive::singlefluid::USD_FLUID_DER > const & dDens = fluid.dDensity(); + // control data + WellControls & wellControls = getWellControls( subRegion ); + + real64 & currentVolRate = + wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentVolRateString() ); + + // bring everything back to host, capture the scalars by reference + forAll< serialPolicy >( 1, [connRate, + dens, + ¤tVolRate, + &iwelemRef] ( localIndex const ) + { + real64 const densInv = 1.0 / dens[iwelemRef][0]; + currentVolRate = connRate[iwelemRef] * densInv; + // tjb compute mass + } ); + + +} + +void SinglePhaseWell::updateFluidModel( WellElementSubRegion & subRegion ) const +{ + GEOS_MARK_FUNCTION; + + arrayView1d< real64 const > const pres = subRegion.getField< well::pressure >(); + arrayView1d< real64 const > const temp = subRegion.getField< well::temperature >(); + + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + SingleFluidBase & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); + + constitutiveUpdatePassThru( fluid, [&]( auto & castedFluid ) + { + typename TYPEOFREF( castedFluid ) ::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); + singlePhaseBaseKernels::FluidUpdateKernel::launch( fluidWrapper, pres, temp ); + } ); +} +void SinglePhaseWell::updateSeparator( WellElementSubRegion & subRegion ) +{ + GEOS_MARK_FUNCTION; + + // the rank that owns the reference well element is responsible for the calculations below. + if( !subRegion.isLocallyOwned() ) + { + return; + } + + localIndex const iwelemRef = subRegion.getTopWellElementIndex(); + + // subRegion data + arrayView1d< real64 const > const pres = + subRegion.getField< well::pressure >(); + + // control data WellControls & wellControls = getWellControls( subRegion ); string const wellControlsName = wellControls.getName(); bool const logSurfaceCondition = isLogLevelActive< logInfo::WellControl >( wellControls.getLogLevel()); integer const useSurfaceConditions = wellControls.useSurfaceConditions(); + + // fluid data + constitutive::SingleFluidBase & fluidSeparator = wellControls.getSingleFluidSeparator(); + arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > const & dens = fluidSeparator.density(); + real64 flashPressure; if( useSurfaceConditions ) { @@ -315,31 +399,21 @@ void SinglePhaseWell::updateVolRateForConstraint( WellElementSubRegion & subRegi flashPressure = pres[iwelemRef]; } } - real64 & currentVolRate = - wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentVolRateString() ); - - arrayView1d< real64 > const & dCurrentVolRate = - wellControls.getReference< array1d< real64 > >( SinglePhaseWell::viewKeyStruct::dCurrentVolRateString() ); - constitutiveUpdatePassThru( fluid, [&]( auto & castedFluid ) + constitutiveUpdatePassThru( fluidSeparator, [&]( auto & castedFluid ) { - typename TYPEOFREF( castedFluid ) ::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); + typename TYPEOFREF( castedFluid ) ::KernelWrapper fluidSeparatorWrapper = castedFluid.createKernelWrapper(); geos::internal::kernelLaunchSelectorThermalSwitch( isThermal(), [&] ( auto ISTHERMAL ) { integer constexpr IS_THERMAL = ISTHERMAL(); - using COFFSET_WJ = singlePhaseWellKernels::ColOffset_WellJac< IS_THERMAL >; // bring everything back to host, capture the scalars by reference - forAll< serialPolicy >( 1, [fluidWrapper, + forAll< serialPolicy >( 1, [fluidSeparatorWrapper, pres, - connRate, dens, - dDens, logSurfaceCondition, &useSurfaceConditions, &flashPressure, - ¤tVolRate, - dCurrentVolRate, &iwelemRef, &wellControlsName] ( localIndex const ) { @@ -350,7 +424,7 @@ void SinglePhaseWell::updateVolRateForConstraint( WellElementSubRegion & subRegi if( useSurfaceConditions ) { // we need to compute the surface density - fluidWrapper.update( iwelemRef, 0, flashPressure ); + fluidSeparatorWrapper.update( iwelemRef, 0, flashPressure ); if( logSurfaceCondition ) { @@ -365,66 +439,53 @@ void SinglePhaseWell::updateVolRateForConstraint( WellElementSubRegion & subRegi } else { - real64 const refPres = pres[iwelemRef]; - fluidWrapper.update( iwelemRef, 0, refPres ); - } - - real64 const densInv = 1.0 / dens[iwelemRef][0]; - currentVolRate = connRate[iwelemRef] * densInv; - - dCurrentVolRate[COFFSET_WJ::dP] = -( useSurfaceConditions == 0 ) * dDens[iwelemRef][0][DerivOffset::dP] * currentVolRate * densInv; - dCurrentVolRate[COFFSET_WJ::dQ] = densInv; - if constexpr ( IS_THERMAL ) - { - dCurrentVolRate[COFFSET_WJ::dT] = -( useSurfaceConditions == 0 ) * dDens[iwelemRef][0][DerivOffset::dT] * currentVolRate * densInv; - } - if( logSurfaceCondition && useSurfaceConditions ) - { - GEOS_LOG_RANK( GEOS_FMT( "{}: total fluid density at surface conditions = {} kg/sm3, total rate = {} kg/s, total surface volumetric rate = {} sm3/s", - wellControlsName, dens[iwelemRef][0], connRate[iwelemRef], currentVolRate ) ); + fluidSeparatorWrapper.update( iwelemRef, 0, flashPressure ); } } ); } ); } ); } -void SinglePhaseWell::updateFluidModel( WellElementSubRegion & subRegion ) const -{ - GEOS_MARK_FUNCTION; - - arrayView1d< real64 const > const pres = subRegion.getField< well::pressure >(); - arrayView1d< real64 const > const temp = subRegion.getField< well::temperature >(); - - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - SingleFluidBase & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); - - constitutiveUpdatePassThru( fluid, [&]( auto & castedFluid ) - { - typename TYPEOFREF( castedFluid ) ::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); - singlePhaseBaseKernels::FluidUpdateKernel::launch( fluidWrapper, pres, temp ); - } ); -} - real64 SinglePhaseWell::updateSubRegionState( WellElementSubRegion & subRegion ) { - // update volumetric rates for the well constraints - // Warning! This must be called before updating the fluid model - updateVolRateForConstraint( subRegion ); + WellControls & wellControls = getWellControls( subRegion ); + if( wellControls.getWellState()) + { + if( m_useNewCode ) + { + // update volumetric rates for the well constraints + // Warning! This must be called before updating the fluid model + //calculateReferenceElementRates( subRegion ); + + // update density in the well elements + updateFluidModel( subRegion ); + updateSeparator( subRegion ); // Calculate fluid properties at control conditions + + // Calculate the reference element rates + calculateReferenceElementRates( subRegion ); + // update the current BHP + updateBHPForConstraint( subRegion ); + } + else + { + // update volumetric rates for the well constraints + // Warning! This must be called before updating the fluid model + calculateReferenceElementRates( subRegion ); - // update density in the well elements - updateFluidModel( subRegion ); + // update density in the well elements + updateFluidModel( subRegion ); - // update the current BHP - updateBHPForConstraint( subRegion ); + // update the current BHP + updateBHPForConstraint( subRegion ); + } - // note: the perforation rates are updated separately - return 0.0; // change in phasevolume fraction doesnt apply + } + return 0.0; // change in phasevolume fraction doesnt apply } - void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) { GEOS_UNUSED_VAR( domain ); - WellControls const & wellControls = getWellControls( subRegion ); + WellControls & wellControls = getWellControls( subRegion ); PerforationData const & perforationData = *subRegion.getPerforationData(); // get the info stored on well elements @@ -453,6 +514,32 @@ void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh if( time_n <= 0.0 || (wellControls.isWellOpen() && !hasNonZeroRate ) ) { + wellControls.setWellState( true ); + if( wellControls.getCurrentConstraint() == nullptr ) + { + if( wellControls.isProducer() ) + { + wellControls.forSubGroups< MinimumBHPConstraint >( [&]( auto & constraint ) + //wellControls.forSubGroups< PhaseProductionConstraint >( [&]( auto & + // constraint + // ) + { + wellControls.setCurrentConstraint( &constraint ); + wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old + } ); + } + else + { + // tjb needed for backward compatibility + //wellControls.forSubGroups< MaximumBHPConstraint >( [&]( auto & constraint ) + wellControls.forSubGroups< TotalVolConstraint< InjectionConstraint > >( [&]( auto & constraint ) + { + wellControls.setCurrentConstraint( &constraint ); + wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old + } ); + } + } + // TODO: change the way we access the flowSolver here SinglePhaseBase const & flowSolver = getParent().getGroup< SinglePhaseBase >( getFlowSolverName() ); PresTempInitializationKernel::SinglePhaseFlowAccessors resSinglePhaseFlowAccessors( mesh.getElemManager(), flowSolver.getName() ); @@ -494,6 +581,25 @@ void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh 0.0, // initialization done at t = 0 wellElemDens, connRate ); + + calculateReferenceElementRates( subRegion ); + WellConstraintBase * constraint = wellControls.getCurrentConstraint(); + constraint->setBHP ( wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentBHPString() )); + constraint->setTotalVolumeRate ( wellControls.getReference< real64 >( + SinglePhaseWell::viewKeyStruct::currentVolRateString() )); + //constraint->setMassRate( wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentMassRateString() )); + // 7) Copy well / fluid dofs to "prop"_n variables + saveState( subRegion ); + } + else if( !hasNonZeroRate ) + { + wellControls.setWellState( false ); + GEOS_LOG_RANK_0( "tjb shut wells "<< subRegion.getName()); + } + else + { + wellControls.setWellState( true ); + } }; @@ -630,11 +736,40 @@ void SinglePhaseWell::assembleSystem( real64 const time, { string const wellDofKey = dofManager.getKey( wellElementDofName()); + if( m_useNewCode ) + { + // selects constraints one of 2 ways + // wellEstimator flag set to 0 => orginal logic rates are computed during update state and constraints are selected every newton + // iteration + // wellEstimator flag > 0 => well esitmator solved for each constraint and then selects the constraint + // => estimator solve only performed first "wellEstimator" iterations + NonlinearSolverParameters const & nonlinearParams = getNonlinearSolverParameters(); + selectWellConstraint( time, dt, nonlinearParams.m_numNewtonIterations, domain ); + } + // assemble the accumulation term in the mass balance equations assembleAccumulationTerms( time, dt, domain, dofManager, localMatrix, localRhs ); // then assemble the pressure relations between well elements assemblePressureRelations( time, dt, domain, dofManager, localMatrix, localRhs ); + { + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + ElementRegionManager & elementRegionManager = mesh.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = getWellControls( subRegion ); + if( !wellControls.getConstraintSwitch() ) + assembleWellConstraintTerms( time, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); + } ); + } ); + } // then compute the perforation rates (later assembled by the coupled solver) computePerforationRates( time, dt, domain ); @@ -985,13 +1120,13 @@ SinglePhaseWell::calculateWellResidualNorm( real64 const & time_n, arrayView1d< real64 const > const & localRhs ) { GEOS_MARK_FUNCTION; - integer numNorm = 1; // mass balance + integer numNorm = 1; // mass balance array1d< real64 > localResidualNorm; array1d< real64 > localResidualNormalizer; if( isThermal() ) { - numNorm = 2; // mass balance and energy balance + numNorm = 2; // mass balance and energy balance } localResidualNorm.resize( numNorm ); localResidualNormalizer.resize( numNorm ); @@ -1102,13 +1237,13 @@ SinglePhaseWell::calculateResidualNorm( real64 const & time_n, arrayView1d< real64 const > const & localRhs ) { GEOS_MARK_FUNCTION; - integer numNorm = 1; // mass balance + integer numNorm = 1; // mass balance array1d< real64 > localResidualNorm; array1d< real64 > localResidualNormalizer; if( isThermal() ) { - numNorm = 2; // mass balance and energy balance + numNorm = 2; // mass balance and energy balance } localResidualNorm.resize( numNorm ); localResidualNormalizer.resize( numNorm ); @@ -1135,51 +1270,54 @@ SinglePhaseWell::calculateResidualNorm( real64 const & time_n, WellControls const & wellControls = getWellControls( subRegion ); - // step 1: compute the norm in the subRegion - if( isThermal() ) + if( wellControls.isWellOpen() ) { - real64 subRegionResidualNorm[2]{}; - thermalSinglePhaseWellKernels::ResidualNormKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( rankOffset, - wellDofKey, - localRhs, - subRegion, - fluid, - wellControls, - time_n, - dt, - m_nonlinearSolverParameters.m_minNormalizer, - subRegionResidualNorm ); - // step 2: reduction across meshBodies/regions/subRegions - - for( integer i=0; i localResidualNorm[i] ) + real64 subRegionResidualNorm[2]{}; + thermalSinglePhaseWellKernels::ResidualNormKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( rankOffset, + wellDofKey, + localRhs, + subRegion, + fluid, + wellControls, + time_n, + dt, + m_nonlinearSolverParameters.m_minNormalizer, + subRegionResidualNorm ); + // step 2: reduction across meshBodies/regions/subRegions + + for( integer i=0; i localResidualNorm[i] ) + { + localResidualNorm[i] = subRegionResidualNorm[i]; + } } } - } - else - { - real64 subRegionResidualNorm[1]{}; - ResidualNormKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( rankOffset, - wellDofKey, - localRhs, - subRegion, - fluid, - wellControls, - time_n, - dt, - m_nonlinearSolverParameters.m_minNormalizer, - subRegionResidualNorm ); - - // step 2: reduction across meshBodies/regions/subRegions - - if( subRegionResidualNorm[0] > localResidualNorm[0] ) + else { - localResidualNorm[0] = subRegionResidualNorm[0]; + real64 subRegionResidualNorm[1]{}; + ResidualNormKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( rankOffset, + wellDofKey, + localRhs, + subRegion, + fluid, + wellControls, + time_n, + dt, + m_nonlinearSolverParameters.m_minNormalizer, + subRegionResidualNorm ); + + // step 2: reduction across meshBodies/regions/subRegions + + if( subRegionResidualNorm[0] > localResidualNorm[0] ) + { + localResidualNorm[0] = subRegionResidualNorm[0]; + } } } } ); @@ -1465,6 +1603,26 @@ void SinglePhaseWell::resetStateToBeginningOfStep( DomainPartition & domain ) } ); } +void SinglePhaseWell::saveState( WellElementSubRegion & subRegion ) +{ + arrayView1d< real64 const > const wellElemPressure = subRegion.getField< well::pressure >(); + arrayView1d< real64 > const wellElemPressure_n = subRegion.getField< well::pressure_n >(); + wellElemPressure_n.setValues< parallelDevicePolicy<> >( wellElemPressure ); + + if( isThermal() ) + { + arrayView1d< real64 const > const wellElemTemperature = subRegion.getField< well::temperature >(); + arrayView1d< real64 > const wellElemTemperature_n = subRegion.getField< well::temperature_n >(); + wellElemTemperature_n.setValues< parallelDevicePolicy<> >( wellElemTemperature ); + } + arrayView1d< real64 const > const connRate = subRegion.getField< well::connectionRate >(); + arrayView1d< real64 > const connRate_n = subRegion.getField< well::connectionRate_n >(); + connRate_n.setValues< parallelDevicePolicy<> >( connRate ); + + SingleFluidBase const & fluid = + getConstitutiveModel< SingleFluidBase >( subRegion, subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ) ); + fluid.saveConvergedState(); +} void SinglePhaseWell::implicitStepSetup( real64 const & time, real64 const & dt, @@ -1608,5 +1766,66 @@ void SinglePhaseWell::printRates( real64 const & time_n, } ); } +bool SinglePhaseWell::evaluateConstraints( real64 const & time_n, + WellElementSubRegion & subRegion ) +{ + WellControls & wellControls = getWellControls( subRegion ); + // create list of all constraints to process + std::vector< WellConstraintBase * > constraintList; + if( wellControls.isProducer() ) + { + constraintList = wellControls.getProdRateConstraints(); + // Solve minimum bhp constraint first + constraintList.insert( constraintList.begin(), wellControls.getMinBHPConstraint() ); + } + else + { + constraintList = wellControls.getInjRateConstraints(); + // Solve maximum bhp constraint first; + constraintList.insert( constraintList.begin(), wellControls.getMaxBHPConstraint() ); + } + // Get current constraint + WellConstraintBase * limitingConstraint = nullptr; + for( auto & constraint : constraintList ) + { + if( constraint->getName() == wellControls.getCurrentConstraint()->getName()) + { + limitingConstraint = constraint; + // tjb. this is likely not needed. set in update state + constraint->setBHP ( wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentBHPString() )); + constraint->setTotalVolumeRate ( wellControls.getReference< real64 >( + SinglePhaseWell::viewKeyStruct::currentVolRateString() )); + + GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), + " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << + limitingConstraint->totalVolumeRate() ); + } + } + + + // Check current against other constraints + for( auto & constraint : constraintList ) + { + + if( limitingConstraint->getName() != constraint->getName()) + { + //std::cout << "Use estimator " << useEstimator << " Evaluating constraint " << constraint.getName() << " against constraint " << + // limitingConstraint->getName() << std::endl; + if( constraint->checkViolation( *limitingConstraint, time_n ) ) + { + wellControls.setControl( static_cast< WellControls::Control >(constraint->getControl()) ); // tjb old + wellControls.setCurrentConstraint( constraint ); + GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), + " Well " << subRegion.getName() << " New Limiting Constraint " << constraint->getName() << " " << constraint->getConstraintValue( time_n ) ); + } + } + } + GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), + " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << limitingConstraint->phaseVolumeRates() << " " << + limitingConstraint->totalVolumeRate() << " " << limitingConstraint->massRate()); + + return true; +} + REGISTER_CATALOG_ENTRY( PhysicsSolverBase, SinglePhaseWell, string const &, Group * const ) }// namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp index c66cb83e6a1..b9294056d26 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp @@ -165,7 +165,7 @@ class SinglePhaseWell : public WellSolverBase * @brief Recompute the volumetric rate that are used in the well constraints * @param subRegion the well subregion containing all the primary and dependent fields */ - virtual void updateVolRateForConstraint( WellElementSubRegion & subRegion ); + virtual void calculateReferenceElementRates( WellElementSubRegion & subRegion ); /** * @brief Recompute the BHP pressure that is used in the well constraints @@ -178,6 +178,11 @@ class SinglePhaseWell : public WellSolverBase * @param subRegion the well subRegion containing the well elements and their associated fields */ virtual void updateFluidModel( WellElementSubRegion & subRegion ) const; + /** + * @brief Update separator model state + * @param subRegion the well subRegion containing the separator + */ + void updateSeparator( WellElementSubRegion & subRegion ); /** * @brief Recompute the perforation rates for all the wells @@ -338,6 +343,10 @@ class SinglePhaseWell : public WellSolverBase protected: + virtual void initializePostInitialConditionsPreSubGroups() override; + + void saveState( WellElementSubRegion & subRegion ); + void printRates( real64 const & time_n, real64 const & dt, DomainPartition & domain ) override; @@ -367,6 +376,14 @@ class SinglePhaseWell : public WellSolverBase WellElementSubRegion const & subRegion, ElementRegionManager const & elemManager ) override; + virtual bool evaluateConstraints( real64 const & time_n, + WellElementSubRegion & subRegion ) override; + + /** + * @brief Create well separator + */ + void createSeparator(); + }; } // namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp index e05279d7d53..3f8bc66d6a5 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp @@ -431,8 +431,8 @@ class WellSolverBase : public PhysicsSolverBase real64 const & dt, DomainPartition & domain ) = 0; - virtual bool evaluateConstraints( real64 const & GEOS_UNUSED_PARAM( time_n ), - WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion )) { return false;}; + virtual bool evaluateConstraints( real64 const & time_n, + WellElementSubRegion & subRegion ) = 0; /// name of the flow solver From 205889f32f11ebecab995e452498af21ea4ae52e Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Mon, 13 Oct 2025 11:33:33 -0700 Subject: [PATCH 10/71] improve naming conventions for well constriant files and classes --- .../physicsSolvers/fluidFlow/CMakeLists.txt | 22 +- .../wells/CompositionalMultiphaseWell.cpp | 100 ++++--- .../fluidFlow/wells/SinglePhaseWell.cpp | 7 +- .../fluidFlow/wells/WellBHPConstraints.cpp | 2 +- .../fluidFlow/wells/WellBHPConstraints.hpp | 2 +- .../fluidFlow/wells/WellConstraintsBase.cpp | 95 +----- .../fluidFlow/wells/WellConstraintsBase.hpp | 278 +----------------- .../fluidFlow/wells/WellControls.cpp | 104 +++++-- .../fluidFlow/wells/WellControls.hpp | 176 ++++++++--- .../wells/WellInjectionConstraint.cpp | 107 +++++++ .../wells/WellInjectionConstraint.hpp | 137 +++++++++ .../wells/WellLiquidRateConstraint.cpp | 87 ++++++ ...aints.hpp => WellLiquidRateConstraint.hpp} | 39 +-- .../wells/WellLiquidRateConstraints.cpp | 79 ----- .../wells/WellMassRateConstraint.cpp | 81 +++++ ...traints.hpp => WellMassRateConstraint.hpp} | 43 ++- .../wells/WellMassRateConstraints.cpp | 72 ----- ....cpp => WellPhaseVolumeRateConstraint.cpp} | 57 ++-- ....hpp => WellPhaseVolumeRateConstraint.hpp} | 42 ++- .../wells/WellProductionConstraint.cpp | 69 +++++ .../wells/WellProductionConstraint.hpp | 105 +++++++ .../wells/WellTotalVolRateConstraints.cpp | 72 ----- .../wells/WellVolumeRateConstraint.cpp | 80 +++++ ...aints.hpp => WellVolumeRateConstraint.hpp} | 29 +- ...tionalMultiphaseWellConstraintKernels.hpp} | 26 +- .../CompositionalMultiphaseWellKernels.cpp | 4 +- .../CompositionalMultiphaseWellKernels.hpp | 4 +- .../SinglePhaseWellConstraintKernels.hpp | 11 +- .../wells/kernels/SinglePhaseWellKernels.cpp | 1 + .../wells/kernels/SinglePhaseWellKernels.hpp | 9 +- ...rmalCompositionalMultiphaseWellKernels.hpp | 10 +- 31 files changed, 1115 insertions(+), 835 deletions(-) create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellInjectionConstraint.cpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellInjectionConstraint.hpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.cpp rename src/coreComponents/physicsSolvers/fluidFlow/wells/{WellLiquidRateConstraints.hpp => WellLiquidRateConstraint.hpp} (81%) delete mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.cpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraint.cpp rename src/coreComponents/physicsSolvers/fluidFlow/wells/{WellMassRateConstraints.hpp => WellMassRateConstraint.hpp} (74%) delete mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.cpp rename src/coreComponents/physicsSolvers/fluidFlow/wells/{WellPhaseRateConstraints.cpp => WellPhaseVolumeRateConstraint.cpp} (51%) rename src/coreComponents/physicsSolvers/fluidFlow/wells/{WellPhaseRateConstraints.hpp => WellPhaseVolumeRateConstraint.hpp} (76%) create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellProductionConstraint.cpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellProductionConstraint.hpp delete mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.cpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellVolumeRateConstraint.cpp rename src/coreComponents/physicsSolvers/fluidFlow/wells/{WellTotalVolRateConstraints.hpp => WellVolumeRateConstraint.hpp} (78%) rename src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/{WellConstraintKernels.hpp => CompositionalMultiphaseWellConstraintKernels.hpp} (96%) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt index cba20d05b19..c7b51561083 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt +++ b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt @@ -117,17 +117,19 @@ set( fluidFlowSolvers_headers wells/WellConstants.hpp wells/WellControls.hpp wells/WellConstraintsBase.hpp + wells/WellInjectionConstraint.hpp + wells/WellProductionConstraint.hpp wells/WellBHPConstraints.hpp - wells/WellTotalVolRateConstraints.hpp - wells/WellMassRateConstraints.hpp - wells/WellPhaseRateConstraints.hpp - wells/WellLiquidRateConstraints.hpp + wells/WellVolumeRateConstraint.hpp + wells/WellMassRateConstraint.hpp + wells/WellPhaseVolumeRateConstraint.hpp + wells/WellLiquidRateConstraint.hpp wells/WellSolverBase.hpp wells/WellSolverBaseFields.hpp wells/LogLevelsInfo.hpp wells/kernels/SinglePhaseWellKernels.hpp wells/kernels/CompositionalMultiphaseWellKernels.hpp - wells/kernels/WellConstraintKernels.hpp + wells/kernels/CompositionalMultiphaseWellConstraintKernels.hpp wells/kernels/SinglePhaseWellConstraintKernels.hpp proppantTransport/ProppantTransport.hpp proppantTransport/ProppantTransportFields.hpp @@ -159,11 +161,13 @@ set( fluidFlowSolvers_sources wells/kernels/SinglePhaseWellKernels.cpp wells/WellControls.cpp wells/WellConstraintsBase.cpp + wells/WellInjectionConstraint.cpp + wells/WellProductionConstraint.cpp wells/WellBHPConstraints.cpp - wells/WellTotalVolRateConstraints.cpp - wells/WellMassRateConstraints.cpp - wells/WellPhaseRateConstraints.cpp - wells/WellLiquidRateConstraints.cpp + wells/WellVolumeRateConstraint.cpp + wells/WellMassRateConstraint.cpp + wells/WellPhaseVolumeRateConstraint.cpp + wells/WellLiquidRateConstraint.cpp wells/WellSolverBase.cpp proppantTransport/ProppantTransport.cpp proppantTransport/ProppantTransportKernels.cpp ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 6eff710a626..defb9f36a3d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -52,11 +52,11 @@ #include "physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp" -#include "physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp" -#include "physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp" -#include "physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp" -#include "physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp" -#include "physicsSolvers/fluidFlow/wells/kernels/WellConstraintKernels.hpp" +#include "physicsSolvers/fluidFlow/wells/WellVolumeRateConstraint.hpp" +#include "physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.hpp" +#include "physicsSolvers/fluidFlow/wells/WellMassRateConstraint.hpp" +#include "physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.hpp" +#include "physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellConstraintKernels.hpp" @@ -445,7 +445,7 @@ void CompositionalMultiphaseWell::validateWellConstraints( real64 const & time_n MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); // tjb - wellControls.forSubGroups< PhaseConstraint< InjectionConstraint >, PhaseConstraint< ProductionConstraint > >( [&]( auto & constraint ) + wellControls.forSubGroups< InjectionConstraint< PhaseVolumeRateConstraint >, ProductionConstraint< PhaseVolumeRateConstraint > >( [&]( auto & constraint ) { constraint.validatePhaseType( fluid ); } ); @@ -1117,7 +1117,7 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh { // tjb needed for backward compatibility //wellControls.forSubGroups< MaximumBHPConstraint >( [&]( auto & constraint ) - wellControls.forSubGroups< TotalVolConstraint< InjectionConstraint > >( [&]( auto & constraint ) + wellControls.forSubGroups< InjectionConstraint< VolumeRateConstraint > >( [&]( auto & constraint ) { wellControls.setCurrentConstraint( &constraint ); wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old @@ -2500,37 +2500,69 @@ void CompositionalMultiphaseWell::assembleWellConstraintTerms( real64 const & ti } WellControls & wellControls = getWellControls( subRegion ); - - wellControls.forSubGroups< MinimumBHPConstraint, PhaseConstraint< ProductionConstraint >, MassConstraint< ProductionConstraint >, TotalVolConstraint< ProductionConstraint >, - LiquidConstraint< ProductionConstraint >, MaximumBHPConstraint, PhaseConstraint< InjectionConstraint >, MassConstraint< InjectionConstraint >, - TotalVolConstraint< InjectionConstraint >, - LiquidConstraint< InjectionConstraint > - >( [&]( auto & constraint ) + if( wellControls.isProducer() ) { - if( constraint.getName() == wellControls.getCurrentConstraint()->getName()) + wellControls.forSubGroups< MinimumBHPConstraint, ProductionConstraint< PhaseVolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, ProductionConstraint< VolumeRateConstraint >, + ProductionConstraint< LiquidRateConstraint > + >( [&]( auto & constraint ) { - // found limiting constraint + if( constraint.getName() == wellControls.getCurrentConstraint()->getName()) + { + // found limiting constraint - // fluid data - constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); - integer isThermal = fluidSeparator.isThermal(); - integer const numComp = fluidSeparator.numFluidComponents(); - geos::internal::kernelLaunchSelectorCompThermSwitch( numComp, isThermal, [&] ( auto NC, auto ISTHERMAL ) + // fluid data + constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); + integer isThermal = fluidSeparator.isThermal(); + integer const numComp = fluidSeparator.numFluidComponents(); + geos::internal::kernelLaunchSelectorCompThermSwitch( numComp, isThermal, [&] ( auto NC, auto ISTHERMAL ) + { + integer constexpr NUM_COMP = NC(); + integer constexpr IS_THERMAL = ISTHERMAL(); + + wellConstraintKernels::ConstraintHelper< NUM_COMP, IS_THERMAL >::assembleConstraintEquation( time_n, + wellControls, + constraint, + subRegion, + dofManager.getKey( wellElementDofName() ), + dofManager.rankOffset(), + localMatrix, + localRhs ); + } ); + } + } ); + } + else + { + wellControls.forSubGroups< MaximumBHPConstraint, InjectionConstraint< PhaseVolumeRateConstraint >, InjectionConstraint< MassRateConstraint >, + InjectionConstraint< VolumeRateConstraint >, + InjectionConstraint< LiquidRateConstraint > + >( [&]( auto & constraint ) + { + if( constraint.getName() == wellControls.getCurrentConstraint()->getName()) { - integer constexpr NUM_COMP = NC(); - integer constexpr IS_THERMAL = ISTHERMAL(); - - wellConstraintKernels::ConstraintHelper< NUM_COMP, IS_THERMAL >::assembleConstraintEquation( time_n, - wellControls, - constraint, - subRegion, - dofManager.getKey( wellElementDofName() ), - dofManager.rankOffset(), - localMatrix, - localRhs ); - } ); - } - } ); + // found limiting constraint + + // fluid data + constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); + integer isThermal = fluidSeparator.isThermal(); + integer const numComp = fluidSeparator.numFluidComponents(); + geos::internal::kernelLaunchSelectorCompThermSwitch( numComp, isThermal, [&] ( auto NC, auto ISTHERMAL ) + { + integer constexpr NUM_COMP = NC(); + integer constexpr IS_THERMAL = ISTHERMAL(); + + wellConstraintKernels::ConstraintHelper< NUM_COMP, IS_THERMAL >::assembleConstraintEquation( time_n, + wellControls, + constraint, + subRegion, + dofManager.getKey( wellElementDofName() ), + dofManager.rankOffset(), + localMatrix, + localRhs ); + } ); + } + } ); + } } void CompositionalMultiphaseWell::assembleWellPressureRelations( real64 const & GEOS_UNUSED_PARAM( time_n ), diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index 4313497a0ad..839fc616411 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -407,6 +407,7 @@ void SinglePhaseWell::updateSeparator( WellElementSubRegion & subRegion ) geos::internal::kernelLaunchSelectorThermalSwitch( isThermal(), [&] ( auto ISTHERMAL ) { integer constexpr IS_THERMAL = ISTHERMAL(); + GEOS_UNUSED_VAR(IS_THERMAL); // bring everything back to host, capture the scalars by reference forAll< serialPolicy >( 1, [fluidSeparatorWrapper, pres, @@ -532,7 +533,7 @@ void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh { // tjb needed for backward compatibility //wellControls.forSubGroups< MaximumBHPConstraint >( [&]( auto & constraint ) - wellControls.forSubGroups< TotalVolConstraint< InjectionConstraint > >( [&]( auto & constraint ) + wellControls.forSubGroups< InjectionConstraint< VolumeRateConstraint > >( [&]( auto & constraint ) { wellControls.setCurrentConstraint( &constraint ); wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old @@ -871,8 +872,8 @@ void SinglePhaseWell::assembleWellConstraintTerms( real64 const & time_n, WellControls & wellControls = getWellControls( subRegion ); { - // tjb wellControls.forSubGroups< BHPConstraint, MassConstraint, TotalVolConstraint >( [&]( auto & constraint ) - wellControls.forSubGroups< BHPConstraint, TotalVolConstraint< InjectionConstraint >, TotalVolConstraint< ProductionConstraint > >( [&]( auto & constraint ) + // tjb wellControls.forSubGroups< BHPConstraint, MassConstraint, VolumeRateConstraint >( [&]( auto & constraint ) + wellControls.forSubGroups< BHPConstraint, InjectionConstraint< VolumeRateConstraint >, ProductionConstraint< VolumeRateConstraint > >( [&]( auto & constraint ) { if( constraint.getName() == wellControls.getCurrentConstraint()->getName()) { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.cpp index 8577c299a0e..1486362f296 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.cpp @@ -14,7 +14,7 @@ */ /* - * @file WellConstraint.cpp + * @file WellBHPConstraints.cpp */ #include "LogLevelsInfo.hpp" diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp index 1ca0a53da24..06a4121ddd7 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp @@ -14,7 +14,7 @@ */ /* - * @file WellControls.hpp + * @file WellBHPConstraints.hpp */ diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp index a0279fbce09..071c86482fb 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp @@ -92,14 +92,8 @@ WellConstraintBase::~WellConstraintBase() void WellConstraintBase::postInputInitialization() { - // check constraint value - GEOS_THROW_IF( m_constraintValue < 0, - getWrapperDataContext( constraintViewStruct::constraintValueKey::constraintValueString() ) << ": Target value is negative", - InputError ); - - - GEOS_THROW_IF( ((m_constraintValue > 0.0 && !m_constraintScheduleTableName.empty())), - getName() << " " << getDataContext() << ": You have provided redundant information for well constraint value ." << + GEOS_THROW_IF( ((m_constraintValue > 0.0 && !m_constraintScheduleTableName.empty())|| (!(m_constraintValue > 0.0) && m_constraintScheduleTableName.empty())), + this->getName() << " " << this->getDataContext() << ": You have provided redundant information for well constraint value ." << " A constraint value and table of constraint values cannot be specified together", InputError ); @@ -110,19 +104,11 @@ void WellConstraintBase::postInputInitialization() m_constraintScheduleTable = &(functionManager.getGroup< TableFunction const >( m_constraintScheduleTableName )); GEOS_THROW_IF( m_constraintScheduleTable->getInterpolationMethod() != TableFunction::InterpolationType::Lower, - getName() << " " << getDataContext() << ": The interpolation method for the schedule table " - << m_constraintScheduleTable->getName() << " should be TableFunction::InterpolationType::Lower", + this->getName() << " " << this->getDataContext() << ": The interpolation method for the schedule table " + << m_constraintScheduleTable->getName() << " should be TableFunction::InterpolationType::Lower", InputError ); } - - GEOS_THROW_IF ((m_constraintValue <= 0.0 && m_constraintScheduleTableName.empty()), - getName() << " " << getDataContext() << ": You need to specify a volume rate constraint. \n" << - "The rate constraint can be specified using " << - "either " << constraintViewStruct::constraintValueKey::constraintValueString() << - " or " << constraintViewStruct::constraintValueKey::constraintScheduleTableNameString(), - InputError ); - } void WellConstraintBase::setNextDtFromTables( real64 const currentTime, real64 & nextDt ) @@ -144,78 +130,5 @@ void WellConstraintBase::setNextDtFromTable( TableFunction const * table, real64 } } -// *** Phase Constraint for Production Well *************************************************************** -ProductionConstraint::ProductionConstraint( string const & name, Group * const parent ) - : WellConstraintBase( name, parent ) -{ - // set rate sign for producers (base class member) - m_rateSign = -1.0; -} - -ProductionConstraint::~ProductionConstraint() -{} - -void ProductionConstraint::postInputInitialization() -{ - // Validate value and table options - WellConstraintBase::postInputInitialization(); - -} - -// *** Phase Constraint for Injection Well *************************************************************** -InjectionConstraint::InjectionConstraint( string const & name, Group * const parent ) - : WellConstraintBase( name, parent ) -{ - // set rate sign for injectors (base class member) - m_rateSign = 1.0; - registerWrapper( injectionStreamKey::injectionStreamString(), &m_injectionStream ). - setDefaultValue( -1 ). - setSizedFromParent( 0 ). - setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Global component densities of the injection stream [moles/m^3 or kg/m^3]" ); - - registerWrapper( injectionStreamKey::injectionTemperatureString(), &m_injectionTemperature ). - setDefaultValue( -1 ). - setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Temperature of the injection stream [K]" ); -} - -InjectionConstraint::~InjectionConstraint() -{} - -void InjectionConstraint::postInputInitialization() -{ - // Validate value and table options - WellConstraintBase::postInputInitialization(); - -// Validate the injection stream and temperature - validateInjectionStream( ); - -} - -void InjectionConstraint::validateInjectionStream( ) -{ - GEOS_THROW_IF( (m_injectionStream.empty() && m_injectionTemperature >= 0) || - (!m_injectionStream.empty() && m_injectionTemperature < 0), - getName() << " " << getDataContext() << ": Both " - << constraintViewStruct::injectionStreamKey::injectionStreamString() << " and " << injectionStreamKey::injectionTemperatureString() - << " must be specified for multiphase simulations", - InputError ); - - if( !m_injectionStream.empty()) - { - real64 sum = 0.0; - for( localIndex ic = 0; ic < m_injectionStream.size(); ++ic ) - { - GEOS_ERROR_IF( m_injectionStream[ic] < 0.0 || m_injectionStream[ic] > 1.0, - getWrapperDataContext( injectionStreamKey::injectionStreamString() ) << ": Invalid injection stream" ); - sum += m_injectionStream[ic]; - } - GEOS_THROW_IF( LvArray::math::abs( 1.0 - sum ) > std::numeric_limits< real64 >::epsilon(), - getWrapperDataContext( injectionStreamKey::injectionStreamString() ) << ": Invalid injection stream", - InputError ); - } -} - } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp index 373acbdd72c..4eaf2b82480 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp @@ -14,123 +14,19 @@ */ /* - * @file WellControls.hpp + * @file WellConstraintBase.hpp */ -#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINT_HPP -#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINT_HPP +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINTBASE_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINTBASE_HPP #include "common/format/EnumStrings.hpp" -#include "dataRepository/Group.hpp" -#include "functions/TableFunction.hpp" +#include "functions/TableFunction.hpp" +#include "dataRepository/Group.hpp" namespace geos { -namespace dataRepository -{ -namespace keys -{ -static constexpr auto wellConstraintBase = "WellConstraintBase"; -} -} - -namespace constraintViewStruct -{ - -struct constraintValueKey -{ - /// String key for the well constraint value - static constexpr char const * constraintValueString() { return "constraintValue"; } - /// string key for constraint values entered table name - static constexpr char const * constraintScheduleTableNameString() { return "constraintScheduleTableName"; } -}; - -struct surfaceConditionsKey -{ - /// String key for checking the rates at surface conditions - static constexpr char const * useSurfaceConditionsString() { return "useSurfaceConditions"; } - /// String key for the surface pressure - static constexpr char const * surfacePressureString() { return "surfacePressure"; } - /// String key for the surface temperature - static constexpr char const * surfaceTemperatureString() { return "surfaceTemperature"; } -}; - -struct injectionStreamKey -{ - /// String key for the well injection stream - static constexpr char const * injectionStreamString() { return "injectionStream"; } - /// String key for the well injection temperature - static constexpr char const * injectionTemperatureString() { return "injectionTemperature"; } -}; - -} -/** - * @brief Register fields required to define surface conditions for constraint - * @param[in] useSurfaceConditions 0 - use reservoir conditions, 1 use specified P & T - * @param[in] surfacePres surface pressure - * @param[in] surfaceTemp surface pressure - */ -template< typename T > -void registerSurfaceConditions( integer & useSurfaceConditions, - real64 & surfacePres, - real64 & surfaceTemp, - T & context ) -{ - context.registerWrapper( constraintViewStruct::surfaceConditionsKey::useSurfaceConditionsString(), &useSurfaceConditions ). - setDefaultValue( 0 ). - setInputFlag( dataRepository::InputFlags::OPTIONAL ). - setDescription( "Flag to specify whether rates are checked at surface or reservoir conditions.\n" - "Equal to 1 for surface conditions, and to 0 for reservoir conditions" ); - - context.registerWrapper( constraintViewStruct::surfaceConditionsKey::surfacePressureString(), &surfacePres ). - setDefaultValue( 0 ). - setInputFlag( dataRepository::InputFlags::OPTIONAL ). - setDescription( "Surface pressure used to compute volumetric rates when surface conditions are used [Pa]" ); - - context.registerWrapper( constraintViewStruct::surfaceConditionsKey::surfaceTemperatureString(), &surfaceTemp ). - setDefaultValue( 0 ). - setInputFlag( dataRepository::InputFlags::OPTIONAL ). - setDescription( "Surface temperature used to compute volumetric rates when surface conditions are used [K]" ); -} - -/** - * @brief Register fields required to define an injection stream. - * @param[in] injectionStream the injection stream vector - * @param[in] injectionTemperature the injection temperature - * @param[in] context class needing fields - */ -template< typename T > -void registerInjectionStream( array1d< real64 > & injectionStream, - real64 & injectionTemperature, - T & context ) -{ - context.registerWrapper( constraintViewStruct::injectionStreamKey::injectionStreamString(), &injectionStream ). - setDefaultValue( -1 ). - setSizedFromParent( 0 ). - setInputFlag( dataRepository::InputFlags::OPTIONAL ). - setDescription( "Global component densities of the injection stream [moles/m^3 or kg/m^3]" ); - - context.registerWrapper( constraintViewStruct::injectionStreamKey::injectionTemperatureString(), &injectionTemperature ). - setDefaultValue( -1 ). - setInputFlag( dataRepository::InputFlags::OPTIONAL ). - setDescription( "Temperature of the injection stream [K]" ); -} -/** - * @brief Validate the surface conditions - * @param[in] useSurfaceConditions 0 - use reservoir conditions, 1 use specified P & T - * @param[in] className owner of fields - * @param[in] dataContext context for error messages - */ -template< typename T > -void validateSurfaceConditions( integer useSurfaceConditions, - std::string const & className, - T const & context ) -{ - GEOS_THROW_IF( useSurfaceConditions != 0 && useSurfaceConditions != 1, - className << " " << context.getDataContext() << ": The flag to select surface/reservoir conditions must be equal to 0 or 1", - InputError ); -} @@ -236,7 +132,7 @@ class WellConstraintBase : public dataRepository::Group * @brief rate constraints to evaluated WHP constraints. * @return true if the constraint is active, false otherwise */ - bool isConstraintActive( ) { return m_isConstraintActive; } + bool isConstraintActive( ) const { return m_isConstraintActive; } /** * @brief Sets constraint active status @@ -269,9 +165,6 @@ class WellConstraintBase : public dataRepository::Group ///@} - // Phase constraint defintion keys - constraintViewStruct::constraintValueKey viewKeysConstraintValue; - /** * @brief Struct to serve as a container for variable strings and keys. * @struct viewKeyStruct @@ -281,6 +174,10 @@ class WellConstraintBase : public dataRepository::Group /// string key for schedule table name static constexpr char const * constraintScheduleTableNameString() { return "constraintScheduleTableName"; } + /// String key for the well constraint value + static constexpr char const * constraintValueString() { return "constraintValue"; } + + } /// ViewKey struct for the WellControls class viewKeysWellConstraint; @@ -381,160 +278,7 @@ class WellConstraintBase : public dataRepository::Group real64 m_rateSign; }; -/** - * @class ProductionConstraint - * @brief This class describes constraint used to control a production well. - */ - -class ProductionConstraint : public WellConstraintBase -{ -public: - /** - * @name Constructor / Destructor - */ - ///@{ - - /** - * @brief Constructor for WellControls Objects. - * @param[in] name the name of this instantiation of WellControls in the repository - * @param[in] parent the parent group of this instantiation of WellControls - */ - explicit ProductionConstraint( string const & name, dataRepository::Group * const parent ); - - /** - * @brief Default destructor. - */ - ~ProductionConstraint() override; - - /** - * @brief Deleted default constructor. - */ - ProductionConstraint() = delete; - - /** - * @brief Deleted copy constructor. - */ - ProductionConstraint( ProductionConstraint const & ) = delete; - - /** - * @brief Deleted move constructor. - */ - ProductionConstraint( ProductionConstraint && ) = delete; - - /** - * @brief Deleted assignment operator. - * @return a reference to a constraint object - */ - ProductionConstraint & operator=( ProductionConstraint const & ) = delete; - - /** - * @brief Deleted move operator. - * @return a reference to a constraint object - */ - ProductionConstraint & operator=( ProductionConstraint && ) = delete; - - ///@} - -protected: - - virtual void postInputInitialization() override; - - static bool isViolated( const real64 & currentValue, const real64 & constraintValue ) - { return currentValue < constraintValue; } -}; - -/** - * @class InjectionConstraint - * @brief This class describes constraint used to control a injection well. - */ - -class InjectionConstraint : public WellConstraintBase -{ -public: - /** - * @name Constructor / Destructor - */ - ///@{ - - /** - * @brief Constructor for WellControls Objects. - * @param[in] name the name of this instantiation of WellControls in the repository - * @param[in] parent the parent group of this instantiation of WellControls - */ - explicit InjectionConstraint( string const & name, dataRepository::Group * const parent ); - - /** - * @brief Default destructor. - */ - ~InjectionConstraint() override; - - /** - * @brief Deleted default constructor. - */ - InjectionConstraint() = delete; - - /** - * @brief Deleted copy constructor. - */ - InjectionConstraint( InjectionConstraint const & ) = delete; - - /** - * @brief Deleted move constructor. - */ - InjectionConstraint( InjectionConstraint && ) = delete; - - /** - * @brief Deleted assignment operator. - * @return a reference to a constraint object - */ - InjectionConstraint & operator=( InjectionConstraint const & ) = delete; - - /** - * @brief Deleted move operator. - * @return a reference to a constraint object - */ - InjectionConstraint & operator=( InjectionConstraint && ) = delete; - - ///@} - - struct injectionStreamKey - { - /// String key for the well injection stream - static constexpr char const * injectionStreamString() { return "injectionStream"; } - /// String key for the well injection temperature - static constexpr char const * injectionTemperatureString() { return "injectionTemperature"; } - }; - - /** - * @brief Const accessor for the composition of the injection stream - * @return a global component fraction vector - */ - arrayView1d< real64 const > getInjectionStream() const { return m_injectionStream; } - - /** - * @brief Const accessor for the temperature of the injection stream - * @return the temperature of the injection stream - */ - real64 getInjectionTemperature() const { return m_injectionTemperature; } - -protected: - - virtual void postInputInitialization() override; - static bool isViolated( const real64 & currentValue, const real64 & constraintValue ) - { return currentValue > constraintValue; } - - void validateInjectionStream(); -private: - - /// Vector with global component fractions at the injector - array1d< real64 > m_injectionStream; - - /// Temperature at the injector - real64 m_injectionTemperature; - -}; - } //namespace geos -#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINT_HPP +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINTBASE_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index af821d219a6..6477de44973 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -128,45 +128,45 @@ Group * WellControls::createChild( string const & childKey, string const & child } else if( childKey == viewKeyStruct::phaseProductionConstraintString() ) { - PhaseConstraint< ProductionConstraint > & phaseConstraint = registerGroup< PhaseConstraint< ProductionConstraint > >( childName ); + ProductionConstraint< PhaseVolumeRateConstraint > & phaseConstraint = registerGroup< ProductionConstraint< PhaseVolumeRateConstraint > >( childName ); m_productionRateConstraintList.emplace_back( &phaseConstraint ); constraint = &phaseConstraint; } else if( childKey == viewKeyStruct::phaseInjectionConstraintString() ) { - PhaseConstraint< InjectionConstraint > & phaseConstraint = registerGroup< PhaseConstraint< InjectionConstraint > >( childName ); + InjectionConstraint< PhaseVolumeRateConstraint > & phaseConstraint = registerGroup< InjectionConstraint< PhaseVolumeRateConstraint > >( childName ); m_injectionRateConstraintList.emplace_back( &phaseConstraint ); constraint = &phaseConstraint; } else if( childKey == viewKeyStruct::totalVolProductionConstraintString() ) { - TotalVolConstraint< ProductionConstraint > & volConstraint = registerGroup< TotalVolConstraint< ProductionConstraint > >( childName ); + ProductionConstraint< VolumeRateConstraint > & volConstraint = registerGroup< ProductionConstraint< VolumeRateConstraint > >( childName ); m_productionRateConstraintList.emplace_back( &volConstraint ); constraint = &volConstraint; } else if( childKey == viewKeyStruct::totalVolInjectionConstraintString() ) { - TotalVolConstraint< InjectionConstraint > & volConstraint = registerGroup< TotalVolConstraint< InjectionConstraint > >( childName ); + InjectionConstraint< VolumeRateConstraint > & volConstraint = registerGroup< InjectionConstraint< VolumeRateConstraint > >( childName ); m_injectionRateConstraintList.emplace_back( &volConstraint ); constraint = &volConstraint; } else if( childKey == viewKeyStruct::massProductionConstraintString() ) { - MassConstraint< ProductionConstraint > & massConstraint = registerGroup< MassConstraint< ProductionConstraint > >( childName ); + ProductionConstraint< MassRateConstraint > & massConstraint = registerGroup< ProductionConstraint< MassRateConstraint > >( childName ); m_productionRateConstraintList.emplace_back( &massConstraint ); constraint = &massConstraint; } else if( childKey == viewKeyStruct::massInjectionConstraintString() ) { - MassConstraint< InjectionConstraint > & massConstraint = registerGroup< MassConstraint< InjectionConstraint > >( childName ); + InjectionConstraint< MassRateConstraint > & massConstraint = registerGroup< InjectionConstraint< MassRateConstraint > >( childName ); m_injectionRateConstraintList.emplace_back( &massConstraint ); constraint = &massConstraint; } else if( childKey == viewKeyStruct::liquidProductionConstraintString() ) { - LiquidConstraint< ProductionConstraint > & liquidConstraint = registerGroup< LiquidConstraint< ProductionConstraint > >( childName ); + ProductionConstraint< LiquidRateConstraint > & liquidConstraint = registerGroup< ProductionConstraint< LiquidRateConstraint > >( childName ); m_productionRateConstraintList.emplace_back( &liquidConstraint ); constraint = &liquidConstraint; } @@ -204,21 +204,15 @@ TableFunction * createWellTable( string const & tableName, void WellControls::postInputInitialization() { - // 1.c) Set the multiplier for the rates - if( isProducer() ) - { - m_rateSign = -1.0; - } - else - { - m_rateSign = 1.0; - } - // 3) check the flag for surface / reservoir conditions GEOS_THROW_IF( m_useSurfaceConditions != 0 && m_useSurfaceConditions != 1, getWrapperDataContext( viewKeyStruct::useSurfaceConditionsString() ) << ": The flag to select surface/reservoir conditions must be equal to 0 or 1", InputError ); + // tjb add more constraint validation + // 1) liquid rate - phase names consistent with fluild model + // 2) at least one bhp and one rate constraint defined + // 3) constraint type and well type compatibility //GEOS_THROW_IF( ((m_targetMassRate > 0.0 && m_useSurfaceConditions==0)), // "WellControls " << getDataContext() << ": Option only valid if useSurfaceConditions set to 1", @@ -357,4 +351,80 @@ void WellControls::setNextDtFromTable( TableFunction const * table, real64 const } } +real64 WellControls::getTargetBHP( real64 const & targetTime ) const +{ + if( isProducer()) + { + return m_minBHPConstraint->getConstraintValue( targetTime ); + } + return m_maxBHPConstraint->getConstraintValue( targetTime ); +} + + +real64 WellControls::getInjectionTemperature() const +{ + real64 injectionTemperature = 0.0; + this->forInjectionConstraints< InjectionConstraint< PhaseVolumeRateConstraint >, InjectionConstraint< VolumeRateConstraint > >( [&] ( auto & constraint ) + { + if( constraint.isConstraintActive()) + { + injectionTemperature = constraint.getInjectionTemperature(); + return; + } + } ); + return injectionTemperature; +} + + +arrayView1d< real64 const > WellControls::getInjectionStream() const +{ + arrayView1d< real64 const > injectionStream; + forInjectionConstraints< InjectionConstraint< PhaseVolumeRateConstraint >, InjectionConstraint< VolumeRateConstraint > >( [&] ( auto & constraint ) + { + if( constraint.isConstraintActive() ) + { + injectionStream = constraint.getInjectionStream(); + return; + } + } ); + + return injectionStream; +} + +integer WellControls::getConstraintPhaseIndex() const +{ + integer phaseIndex = -1; + + if( isProducer() ) + { + forProductionConstraints< ProductionConstraint< PhaseVolumeRateConstraint > >( [&] ( auto & constraint ) + { + if( constraint.isConstraintActive() ) + { + phaseIndex = constraint.getPhaseIndex(); + } + } ); + } + else + { + forInjectionConstraints< InjectionConstraint< PhaseVolumeRateConstraint > >( [&] ( auto & constraint ) + { + if( constraint.isConstraintActive() ) + { + phaseIndex = constraint.getPhaseIndex(); + } + } ); + } + + return phaseIndex; +} + +real64 WellControls::getReferenceElevation() const +{ + if( isProducer () ) + { + return getMinBHPConstraint()->getReferenceElevation(); + } + return getMaxBHPConstraint()->getReferenceElevation(); +} } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp index 1c5b04e2459..17dd29aeea1 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp @@ -26,11 +26,13 @@ #include "functions/TableFunction.hpp" #include "constitutive/fluid/multifluid/MultiFluidBase.hpp" +#include "physicsSolvers/fluidFlow/wells/WellInjectionConstraint.hpp" +#include "physicsSolvers/fluidFlow/wells/WellProductionConstraint.hpp" #include "physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp" -#include "physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp" -#include "physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp" -#include "physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp" -#include "physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellVolumeRateConstraint.hpp" +#include "physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.hpp" +#include "physicsSolvers/fluidFlow/wells/WellMassRateConstraint.hpp" +#include "physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.hpp" #include "constitutive/fluid/multifluid/MultiFluidBase.hpp" #include "constitutive/fluid/singlefluid/SingleFluidBase.hpp" namespace geos @@ -141,7 +143,112 @@ class WellControls : public dataRepository::Group virtual void expandObjectCatalogs() override; + /** + * @brief Apply a given functor to a container if the container can be + * cast to one of the specified types. + * @tparam CASTTYPE the first type that will be used in the attempted casting of container + * @tparam CASTTYPES a variadic list of types that will be used in the attempted casting of container + * @tparam CONTAINERTYPE the type of container + * @tparam LAMBDA the type of lambda function to call in the function + * @param[in] container a pointer to the container which will be passed to the lambda function + * @param[in] lambda the lambda function to call in the function + * @return a boolean to indicate whether the lambda was successfully applied to the container. + */ + template< typename T0, typename T1, typename ... CASTTYPES, typename CONTAINERTYPE, typename LAMBDA > + static bool applyLambdaToContainer( CONTAINERTYPE container, LAMBDA && lambda ) + { + using Pointee = std::remove_pointer_t< std::remove_reference_t< CONTAINERTYPE > >; + using T = std::conditional_t< std::is_const< Pointee >::value, T0 const, T0 >; + T * const castedContainer = dynamic_cast< T * >( container ); + + if( castedContainer != nullptr ) + { + lambda( *castedContainer ); + return true; + } + + return applyLambdaToContainer< T1, CASTTYPES... >( container, std::forward< LAMBDA >( lambda ) ); + } + + // Base case: no more types to try + template< typename CONTAINERTYPE, typename LAMBDA > + static bool applyLambdaToContainer( CONTAINERTYPE /*container*/, LAMBDA && /*lambda*/ ) + { + return false; + } + + // Single-type overload: try only T0 and stop + template< typename T0, typename CONTAINERTYPE, typename LAMBDA > + static bool applyLambdaToContainer( CONTAINERTYPE container, LAMBDA && lambda ) + { + using Pointee = std::remove_pointer_t< std::remove_reference_t< CONTAINERTYPE > >; + using T = std::conditional_t< std::is_const< Pointee >::value, T0 const, T0 >; + T * const castedContainer = dynamic_cast< T * >( container ); + + if( castedContainer != nullptr ) + { + lambda( *castedContainer ); + return true; + } + + return false; + } + + + /** + * @copydoc forInjectionConstraints(LAMBDA &&) + */ + template< typename GROUPTYPE = Group, typename ... GROUPTYPES, typename LAMBDA > + void forInjectionConstraints( LAMBDA && lambda ) const + { + for( auto const * constraintIter : m_injectionRateConstraintList ) + { + applyLambdaToContainer< GROUPTYPE, GROUPTYPES... >( constraintIter, [&]( auto const & castedSubGroup ) + { + lambda( castedSubGroup ); + } ); + } + } + + // non-const overload + template< typename GROUPTYPE = Group, typename ... GROUPTYPES, typename LAMBDA > + void forInjectionConstraints( LAMBDA && lambda ) + { + for( auto * constraintIter : m_injectionRateConstraintList ) + { + applyLambdaToContainer< GROUPTYPE, GROUPTYPES... >( constraintIter, [&]( auto & castedSubGroup ) + { + lambda( castedSubGroup ); + } ); + } + } + /** + * @copydoc forProductionConstraints(LAMBDA &&) + */ + template< typename GROUPTYPE = Group, typename ... GROUPTYPES, typename LAMBDA > + void forProductionConstraints( LAMBDA && lambda ) const + { + for( auto const * constraintIter : m_productionRateConstraintList ) + { + applyLambdaToContainer< GROUPTYPE, GROUPTYPES... >( constraintIter, [&]( auto const & castedSubGroup ) + { + lambda( castedSubGroup ); + } ); + } + } + // non-const overload + template< typename GROUPTYPE = Group, typename ... GROUPTYPES, typename LAMBDA > + void forProductionConstraints( LAMBDA && lambda ) + { + for( auto * constraintIter : m_productionRateConstraintList ) + { + applyLambdaToContainer< GROUPTYPE, GROUPTYPES... >( constraintIter, [&]( auto & castedSubGroup ) + { + lambda( castedSubGroup ); + } ); + } + } /** * @name Getters / Setters */ @@ -177,57 +284,34 @@ class WellControls : public dataRepository::Group * @param[in] targetTime time at which to evaluate the constraint * @return the injector maximum bottom hole pressure or producer minimum bottom hole pressure */ - real64 getTargetBHP( real64 const & targetTime ) const - { - if( isProducer()) - { - return m_minBHPConstraint->getConstraintValue( targetTime ); - } - return m_maxBHPConstraint->getConstraintValue( targetTime ); - } + real64 getTargetBHP( real64 const & targetTime ) const; + /** * @brief Const accessor for the temperature of the injection stream * @return the temperature of the injection stream */ - real64 getInjectionTemperature() const - { - real64 injectionTemperature = 0.0; - for( auto c : m_injectionRateConstraintList ) - if( c->isConstraintActive()) - { - injectionTemperature = dynamic_cast< InjectionConstraint * >(c)->getInjectionTemperature(); - break; - } - return injectionTemperature; - } + real64 getInjectionTemperature() const; + /** * @brief Const accessor for the injection stream * @return the injection stream */ - arrayView1d< real64 const > getInjectionStream() const - { - arrayView1d< real64 const > injectionStream; - for( auto c : m_injectionRateConstraintList ) - if( c->isConstraintActive()) - { - injectionStream = dynamic_cast< InjectionConstraint * >(c)->getInjectionStream(); - break; - } - return injectionStream; - } + arrayView1d< real64 const > getInjectionStream() const; + + + /** + * @brief Const accessor for the phase constraint index + * @return phase index associated with phase constraint + */ + integer getConstraintPhaseIndex() const; + /** * @brief Return the reference elvation where pressure constraint is measured * @return vertical location of constraint */ - real64 getReferenceElevation() const - { - if( isProducer () ) - { - return getMinBHPConstraint()->getReferenceElevation(); - } - return getMaxBHPConstraint()->getReferenceElevation(); - } + real64 getReferenceElevation() const; + /** * @brief Getter for the flag specifying whether we check rates at surface or reservoir conditions @@ -525,11 +609,15 @@ class WellControls : public dataRepository::Group }; -ENUM_STRINGS( WellControls::Type, + +// Use local aliases to avoid accidental macro expansion of the tokens 'Type' or 'Control' +using WellControls_Type = WellControls::Type; +ENUM_STRINGS( WellControls_Type, "producer", "injector" ); -ENUM_STRINGS( WellControls::Control, +using WellControls_Control = WellControls::Control; +ENUM_STRINGS( WellControls_Control, "BHP", "phaseVolRate", "totalVolRate", diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellInjectionConstraint.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellInjectionConstraint.cpp new file mode 100644 index 00000000000..708a8c088fa --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellInjectionConstraint.cpp @@ -0,0 +1,107 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellInjectionConstraint.cpp + */ + +#include "LogLevelsInfo.hpp" +#include "WellInjectionConstraint.hpp" +#include "WellConstants.hpp" +#include "dataRepository/InputFlags.hpp" +#include "functions/FunctionManager.hpp" + +#include "WellLiquidRateConstraint.hpp" +#include "WellMassRateConstraint.hpp" +#include "WellPhaseVolumeRateConstraint.hpp" +#include "WellVolumeRateConstraint.hpp" + +namespace geos +{ + +template< typename ConstraintRateType > +InjectionConstraint< ConstraintRateType >::InjectionConstraint( string const & name, Group * const parent ) + : ConstraintRateType( name, parent ) +{ + // set rate sign for injectors (base class member) + this->m_rateSign = 1.0; + classtype::registerWrapper( injectionStreamKey::injectionStreamString(), &m_injectionStream ). + setDefaultValue( -1 ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Global component densities of the injection stream [moles/m^3 or kg/m^3]" ); + + InjectionConstraint< ConstraintRateType >::registerWrapper( injectionStreamKey::injectionTemperatureString(), &m_injectionTemperature ). + setDefaultValue( -1 ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Temperature of the injection stream [K]" ); +} +template< typename ConstraintRateType > +InjectionConstraint< ConstraintRateType >::~InjectionConstraint() +{} +template< typename ConstraintRateType > +void InjectionConstraint< ConstraintRateType >::postInputInitialization() +{ + // Validate value and table options + ConstraintRateType::postInputInitialization(); + +// Validate the injection stream and temperature + validateInjectionStream( ); + +} +template< typename ConstraintRateType > +void InjectionConstraint< ConstraintRateType >::validateInjectionStream( ) +{ + GEOS_THROW_IF( (m_injectionStream.empty() && m_injectionTemperature >= 0) || + (!m_injectionStream.empty() && m_injectionTemperature < 0), + this->getName() << " " << this->getDataContext() << ": Both " + << injectionStreamKey::injectionStreamString() << " and " << injectionStreamKey::injectionTemperatureString() + << " must be specified for multiphase simulations", + InputError ); + + if( !m_injectionStream.empty()) + { + real64 sum = 0.0; + for( localIndex ic = 0; ic < m_injectionStream.size(); ++ic ) + { + GEOS_ERROR_IF( m_injectionStream[ic] < 0.0 || m_injectionStream[ic] > 1.0, + classtype::getWrapperDataContext( injectionStreamKey::injectionStreamString() ) << ": Invalid injection stream" ); + sum += m_injectionStream[ic]; + } + GEOS_THROW_IF( LvArray::math::abs( 1.0 - sum ) > std::numeric_limits< real64 >::epsilon(), + classtype::getWrapperDataContext( injectionStreamKey::injectionStreamString() ) << ": Invalid injection stream", + InputError ); + } +} + +// Register concrete wrapper constraint types and instantiate templates. + +using LiquidInjectionConstraint = InjectionConstraint< LiquidRateConstraint >; +REGISTER_CATALOG_ENTRY( WellConstraintBase, LiquidInjectionConstraint, string const &, Group * const ) +template class InjectionConstraint< LiquidRateConstraint >; + +using MassInjectionConstraint = InjectionConstraint< MassRateConstraint >; +REGISTER_CATALOG_ENTRY( WellConstraintBase, MassInjectionConstraint, string const &, Group * const ) +template class InjectionConstraint< MassRateConstraint >; + +using PhaseInjectionConstraint = InjectionConstraint< PhaseVolumeRateConstraint >; +REGISTER_CATALOG_ENTRY( WellConstraintBase, PhaseInjectionConstraint, string const &, Group * const ) +template class InjectionConstraint< PhaseVolumeRateConstraint >; + +using TotalVolInjectionConstraint = InjectionConstraint< VolumeRateConstraint >; +REGISTER_CATALOG_ENTRY( WellConstraintBase, TotalVolInjectionConstraint, string const &, Group * const ) +template class InjectionConstraint< VolumeRateConstraint >; + +} diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellInjectionConstraint.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellInjectionConstraint.hpp new file mode 100644 index 00000000000..5e186534978 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellInjectionConstraint.hpp @@ -0,0 +1,137 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellInjectionConstraint.hpp + */ + + +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLINJECTIONCONSTRAINT_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLINJECTIONCONSTRAINT_HPP + +#include "common/format/EnumStrings.hpp" +#include "dataRepository/Group.hpp" +#include "functions/TableFunction.hpp" + +namespace geos +{ + +using namespace dataRepository; +/** + * @class InjectionConstraint + * @brief This class describes constraint used to control a injection well. + */ + +template< typename ConstraintType > +class InjectionConstraint : public ConstraintType +{ +public: + typedef InjectionConstraint< ConstraintType > classtype; + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for WellControls Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit InjectionConstraint( string const & name, dataRepository::Group * const parent ); + + /** + * @brief Default destructor. + */ + ~InjectionConstraint() override; + + /** + * @brief Deleted default constructor. + */ + InjectionConstraint() = delete; + + /** + * @brief Deleted copy constructor. + */ + InjectionConstraint( InjectionConstraint const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + InjectionConstraint( InjectionConstraint && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + InjectionConstraint & operator=( InjectionConstraint const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + InjectionConstraint & operator=( InjectionConstraint && ) = delete; + + ///@} + + /** + * @brief name of the node manager in the object catalog + * @return string that contains the catalog name to generate a new Constraint object through the object catalog. + */ + static string catalogName() + { + return "InjectionConstraint"+ConstraintType::catalogName(); + } + + struct injectionStreamKey + { + /// String key for the well injection stream + static constexpr char const * injectionStreamString() { return "injectionStream"; } + /// String key for the well injection temperature + static constexpr char const * injectionTemperatureString() { return "injectionTemperature"; } + }; + + /** + * @brief Const accessor for the composition of the injection stream + * @return a global component fraction vector + */ + arrayView1d< real64 const > getInjectionStream() const { return m_injectionStream; } + + /** + * @brief Const accessor for the temperature of the injection stream + * @return the temperature of the injection stream + */ + real64 getInjectionTemperature() const { return m_injectionTemperature; } + +protected: + + virtual void postInputInitialization() override; + static bool isViolated( const real64 & currentValue, const real64 & constraintValue ) + { return currentValue > constraintValue; } + + void validateInjectionStream(); +private: + + /// Vector with global component fractions at the injector + array1d< real64 > m_injectionStream; + + /// Temperature at the injector + real64 m_injectionTemperature; + +}; + + +} //namespace geos + +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLINJECTIONCONSTRAINT_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.cpp new file mode 100644 index 00000000000..dab8b969486 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.cpp @@ -0,0 +1,87 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellLiquidRateConstraint.cpp + */ + +#include "LogLevelsInfo.hpp" +#include "WellLiquidRateConstraint.hpp" +#include "WellConstants.hpp" +#include "dataRepository/InputFlags.hpp" +#include "functions/FunctionManager.hpp" + +namespace geos +{ + +using namespace dataRepository; + + +LiquidRateConstraint::LiquidRateConstraint( string const & name, Group * const parent ) + : WellConstraintBase( name, parent ) +{ + this->registerWrapper( viewKeyStruct::liquidRateString(), &this->m_constraintValue ). + setDefaultValue( 0.0 ). + setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). + setDescription( "Phase rate, (if useSurfaceCondSitions: [surface m^3/s]; else [reservoir m^3/s]) " ); + + this->registerWrapper( viewKeyStruct::phaseNamesString(), &m_phaseNames ). + setRTTypeName( rtTypes::CustomTypes::groupNameRef ). + setDefaultValue( "" ). + setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). + setDescription( "Name of the target phases" ); +} + +LiquidRateConstraint::~LiquidRateConstraint() +{} + +void LiquidRateConstraint::postInputInitialization() +{ + // Validate table options + WellConstraintBase::postInputInitialization(); + + // check constraint value + GEOS_THROW_IF( m_constraintValue < 0, + getWrapperDataContext( viewKeyStruct::liquidRateString() ) << ": Target value is negative", + InputError ); + + GEOS_THROW_IF ((m_constraintValue <= 0.0 && m_constraintScheduleTableName.empty()), + getName() << " " << getDataContext() << ": You need to specify a liquid rate constraint. \n" << + "The rate constraint can be specified using " << + "either " << viewKeyStruct::liquidRateString() << + " or " << WellConstraintBase::viewKeyStruct::constraintScheduleTableNameString(), + InputError ); +} + + +bool LiquidRateConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const +{ + real64 const currentValue = currentConstraint.liquidRate(); + real64 const constraintValue = this->getConstraintValue( currentTime ); + if( this->m_rateSign < 0.0 ) + { + // production: violated when current < constraint + return currentValue < constraintValue; + } + else + { + // injection: violated when current > constraint + return currentValue > constraintValue; + } +} + +} //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.hpp similarity index 81% rename from src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp rename to src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.hpp index bd9938c1510..45ef0b58a98 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.hpp @@ -14,15 +14,15 @@ */ /* - * @file WellLiquidRateConstraints.hpp + * @file WellLiquidRateConstraint.hpp */ -#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLLIQUIDRATECONSTRAINTS_HPP -#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLLIQUIDRATECONSTRAINTS_HPP +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLLIQUIDRATECONSTRAINT_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLLIQUIDRATECONSTRAINT_HPP #include "common/format/EnumStrings.hpp" -#include "dataRepository/Group.hpp" + #include "functions/TableFunction.hpp" #include "WellConstraintsBase.hpp" @@ -31,12 +31,12 @@ namespace geos /** - * @class LiquidConstraint + * @class LiquidRateConstraint * @brief This class describes a Liquid rate constraint used to control of type WellConstraintType */ -template< typename WellConstraintType > -class LiquidConstraint : public WellConstraintType + +class LiquidRateConstraint : public WellConstraintBase { public: @@ -51,40 +51,40 @@ class LiquidConstraint : public WellConstraintType * @param[in] name the name of this instantiation of WellControls in the repository * @param[in] parent the parent group of this instantiation of WellControls */ - explicit LiquidConstraint( string const & name, dataRepository::Group * const parent ); + explicit LiquidRateConstraint( string const & name, dataRepository::Group * const parent ); /** * @brief Default destructor. */ - ~LiquidConstraint() override; + ~LiquidRateConstraint() override; /** * @brief Deleted default constructor. */ - LiquidConstraint() = delete; + LiquidRateConstraint() = delete; /** * @brief Deleted copy constructor. */ - LiquidConstraint( LiquidConstraint const & ) = delete; + LiquidRateConstraint( LiquidRateConstraint const & ) = delete; /** * @brief Deleted move constructor. */ - LiquidConstraint( LiquidConstraint && ) = delete; + LiquidRateConstraint( LiquidRateConstraint && ) = delete; /** * @brief Deleted assignment operator. * @return a reference to a constraint object */ - LiquidConstraint & operator=( LiquidConstraint const & ) = delete; + LiquidRateConstraint & operator=( LiquidRateConstraint const & ) = delete; /** * @brief Deleted move operator. * @return a reference to a constraint object */ - LiquidConstraint & operator=( LiquidConstraint && ) = delete; + LiquidRateConstraint & operator=( LiquidRateConstraint && ) = delete; /** * @brief name of the node manager in the object catalog @@ -92,14 +92,7 @@ class LiquidConstraint : public WellConstraintType */ static string catalogName() { - if constexpr ( std::is_same_v< WellConstraintType, InjectionConstraint > ) // special case - { - return "LiquidInjectionConstraint"; - } - else // default - { - return "LiquidProductionConstraint"; - } + return "LiquidRateConstraint"; } ///@} @@ -174,4 +167,4 @@ class LiquidConstraint : public WellConstraintType } //namespace geos -#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINT_HPP +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLLiquidRateConstraint_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.cpp deleted file mode 100644 index 43d017d36c6..00000000000 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * SPDX-License-Identifier: LGPL-2.1-only - * - * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 TotalEnergies - * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University - * Copyright (c) 2023-2024 Chevron - * Copyright (c) 2019- GEOS/GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/* - * @file WellConstraint.cpp - */ - -#include "LogLevelsInfo.hpp" -#include "WellLiquidRateConstraints.hpp" -#include "WellConstants.hpp" -#include "dataRepository/InputFlags.hpp" -#include "functions/FunctionManager.hpp" - - -namespace geos -{ - -using namespace dataRepository; - -template< typename WellConstraintType > -LiquidConstraint< WellConstraintType >::LiquidConstraint( string const & name, Group * const parent ) - : WellConstraintType( name, parent ) -{ - this->registerWrapper( viewKeyStruct::liquidRateString(), &this->m_constraintValue ). - setDefaultValue( 0.0 ). - setInputFlag( InputFlags::OPTIONAL ). - setRestartFlags( RestartFlags::WRITE_AND_READ ). - setDescription( "Phase rate, (if useSurfaceCondSitions: [surface m^3/s]; else [reservoir m^3/s]) " ); - - this->registerWrapper( viewKeyStruct::phaseNamesString(), &m_phaseNames ). - setRTTypeName( rtTypes::CustomTypes::groupNameRef ). - setDefaultValue( "" ). - setInputFlag( InputFlags::OPTIONAL ). - setRestartFlags( RestartFlags::WRITE_AND_READ ). - setDescription( "Name of the target phase" ); -} -template< typename WellConstraintType > -LiquidConstraint< WellConstraintType >::~LiquidConstraint() -{} -template< typename WellConstraintType > -void LiquidConstraint< WellConstraintType >::postInputInitialization() -{ - // Validate value and table options - WellConstraintBase::postInputInitialization(); -} - -template< typename WellConstraintType > -bool LiquidConstraint< WellConstraintType >::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const -{ - return WellConstraintType::isViolated( currentConstraint.liquidRate(), this->getConstraintValue( currentTime )); -} - -namespace -{ - -typedef LiquidConstraint< InjectionConstraint > LiquidInjectionConstraint; -REGISTER_CATALOG_ENTRY( WellConstraintBase, LiquidInjectionConstraint, string const &, Group * const ) -typedef LiquidConstraint< ProductionConstraint > LiquidProductionConstraint; -REGISTER_CATALOG_ENTRY( WellConstraintBase, LiquidProductionConstraint, string const &, Group * const ) - -} - -// Explicit template instantiations to ensure constructors are emitted for registration -template class LiquidConstraint< InjectionConstraint >; -template class LiquidConstraint< ProductionConstraint >; - -} //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraint.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraint.cpp new file mode 100644 index 00000000000..6851a033f8b --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraint.cpp @@ -0,0 +1,81 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellMassRateConstraints.cpp + */ + +#include "LogLevelsInfo.hpp" +#include "WellMassRateConstraint.hpp" +#include "WellConstants.hpp" +#include "dataRepository/InputFlags.hpp" +#include "functions/FunctionManager.hpp" + +namespace geos +{ + +using namespace dataRepository; + +MassRateConstraint::MassRateConstraint( string const & name, Group * const parent ) + : WellConstraintBase( name, parent ) +{ + this->setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); + + this->registerWrapper( viewKeyStruct::massRateString(), &this->m_constraintValue ). + setDefaultValue( 0.0 ). + setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). + setDescription( "Maximum mass rate (kg/s)" ); +} + +MassRateConstraint::~MassRateConstraint() +{} + + +void MassRateConstraint::postInputInitialization() +{ + // Validate table options + WellConstraintBase::postInputInitialization(); + + // check constraint value + GEOS_THROW_IF( m_constraintValue < 0, + getWrapperDataContext( viewKeyStruct::massRateString() ) << ": Target value is negative", + InputError ); + + GEOS_THROW_IF ((m_constraintValue <= 0.0 && m_constraintScheduleTableName.empty()), + getName() << " " << getDataContext() << ": You need to specify a mass rate constraint. \n" << + "The rate constraint can be specified using " << + "either " << viewKeyStruct::massRateString() << + " or " << WellConstraintBase::viewKeyStruct::constraintScheduleTableNameString(), + InputError ); +} + + +bool MassRateConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime )const +{ + // isViolated is defined as a static method on the specific WellConstraintType (Injection/Production) + // Evaluate violation according to the sign set for injectors/producers + real64 const currentValue = currentConstraint.massRate(); + real64 const constraintValue = this->getConstraintValue( currentTime ); + if( this->m_rateSign < 0.0 ) + { + return currentValue < constraintValue; + } + else + { + return currentValue > constraintValue; + } +} +} //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraint.hpp similarity index 74% rename from src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp rename to src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraint.hpp index eb7af0f8a3d..6cd6703ba36 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraint.hpp @@ -14,12 +14,12 @@ */ /* - * @file WellMassRateConstraints.hpp + * @file WellMassRateConstraint.hpp */ -#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLMASSRATECONSTRAINTS_HPP -#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLMASSRATECONSTRAINTS_HPP +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLMASSRATECONSTRAINT_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLMASSRATECONSTRAINT_HPP #include "common/format/EnumStrings.hpp" #include "dataRepository/Group.hpp" @@ -29,11 +29,11 @@ namespace geos { /** - * @class MassConstraint + * @class MassRateConstraint * @brief This class describes a mass rate constraint used to control a well. */ -template< typename WellConstraintType > -class MassConstraint : public WellConstraintType + +class MassRateConstraint : public WellConstraintBase { public: @@ -47,40 +47,40 @@ class MassConstraint : public WellConstraintType * @param[in] name the name of this instantiation of WellControls in the repository * @param[in] parent the parent group of this instantiation of WellControls */ - explicit MassConstraint( string const & name, dataRepository::Group * const parent ); + explicit MassRateConstraint( string const & name, dataRepository::Group * const parent ); /** * @brief Default destructor. */ - ~MassConstraint() override; + ~MassRateConstraint() override; /** * @brief Deleted default constructor. */ - MassConstraint() = delete; + MassRateConstraint() = delete; /** * @brief Deleted copy constructor. */ - MassConstraint( MassConstraint const & ) = delete; + MassRateConstraint( MassRateConstraint const & ) = delete; /** * @brief Deleted move constructor. */ - MassConstraint( MassConstraint && ) = delete; + MassRateConstraint( MassRateConstraint && ) = delete; /** * @brief Deleted assignment operator. * @return a reference to a constraint object */ - MassConstraint & operator=( MassConstraint const & ) = delete; + MassRateConstraint & operator=( MassRateConstraint const & ) = delete; /** * @brief Deleted move operator. * @return a reference to a constraint object */ - MassConstraint & operator=( MassConstraint && ) = delete; + MassRateConstraint & operator=( MassRateConstraint && ) = delete; /** * @brief name of the node manager in the object catalog @@ -88,17 +88,16 @@ class MassConstraint : public WellConstraintType */ static string catalogName() { - if constexpr ( std::is_same_v< WellConstraintType, InjectionConstraint > ) // special case - { - return "MassInjectionConstraint"; - } - else // default - { - return "MassProductionConstraint"; - } + return "MassRateConstraint"; } ///@} + struct viewKeyStruct + { + /// String key for the well target rate + static constexpr char const * massRateString() { return "massRate"; } + }; + /** * @name Getters / Setters */ @@ -118,4 +117,4 @@ class MassConstraint : public WellConstraintType } //namespace geos -#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINT_HPP +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLMASSRATECONSTRAINT_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.cpp deleted file mode 100644 index 62bc1112264..00000000000 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraints.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * SPDX-License-Identifier: LGPL-2.1-only - * - * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 TotalEnergies - * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University - * Copyright (c) 2023-2024 Chevron - * Copyright (c) 2019- GEOS/GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/* - * @file WellMassRateConstraints.cpp - */ - -#include "LogLevelsInfo.hpp" -#include "WellMassRateConstraints.hpp" -#include "WellConstants.hpp" -#include "dataRepository/InputFlags.hpp" -#include "functions/FunctionManager.hpp" - - -namespace geos -{ - -using namespace dataRepository; - -template< typename WellConstraintType > -MassConstraint< WellConstraintType >::MassConstraint( string const & name, Group * const parent ) - : WellConstraintType( name, parent ) -{ - this->setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); - - this->registerWrapper( constraintViewStruct::constraintValueKey::constraintValueString(), &this->m_constraintValue ). - setDefaultValue( 0.0 ). - setInputFlag( InputFlags::OPTIONAL ). - setRestartFlags( RestartFlags::WRITE_AND_READ ). - setDescription( "Maximum mass rate (kg/s)" ); -} -template< typename WellConstraintType > -MassConstraint< WellConstraintType >::~MassConstraint() -{} - -template< typename WellConstraintType > -void MassConstraint< WellConstraintType >::postInputInitialization() -{ - // Validate value and table options - WellConstraintBase::postInputInitialization(); - -} - -template< typename WellConstraintType > -bool MassConstraint< WellConstraintType >::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime )const -{ - // isViolated is defined as a static method on the specific WellConstraintType (Injection/Production) - return WellConstraintType::isViolated( currentConstraint.massRate(), this->getConstraintValue( currentTime )); -} - -typedef MassConstraint< InjectionConstraint > MassInjectionConstraint; -REGISTER_CATALOG_ENTRY( WellConstraintBase, MassInjectionConstraint, string const &, Group * const ) -typedef MassConstraint< ProductionConstraint > MassProductionConstraint; -REGISTER_CATALOG_ENTRY( WellConstraintBase, MassProductionConstraint, string const &, Group * const ) - -// Explicit template instantiations to ensure symbols are emitted for the concrete types -template class MassConstraint< InjectionConstraint >; -template class MassConstraint< ProductionConstraint >; - -} //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.cpp similarity index 51% rename from src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.cpp rename to src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.cpp index 11d3a460d4e..533848b97a3 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.cpp @@ -14,11 +14,11 @@ */ /* - * @file WellConstraint.cpp + * @file WellPhaseVolumeRateConstraint.cpp */ #include "LogLevelsInfo.hpp" -#include "WellPhaseRateConstraints.hpp" +#include "WellPhaseVolumeRateConstraint.hpp" #include "WellConstants.hpp" #include "dataRepository/InputFlags.hpp" #include "functions/FunctionManager.hpp" @@ -30,9 +30,8 @@ namespace geos using namespace dataRepository; -template< typename WellConstraintType > -PhaseConstraint< WellConstraintType >::PhaseConstraint( string const & name, Group * const parent ) - : WellConstraintType( name, parent ) +PhaseVolumeRateConstraint::PhaseVolumeRateConstraint( string const & name, Group * const parent ) + : WellConstraintBase( name, parent ) { this->setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); @@ -50,34 +49,40 @@ PhaseConstraint< WellConstraintType >::PhaseConstraint( string const & name, Gro setDescription( "Name of the target phase" ); } -template< typename WellConstraintType > -PhaseConstraint< WellConstraintType >::~PhaseConstraint() +PhaseVolumeRateConstraint::~PhaseVolumeRateConstraint() {} -template< typename WellConstraintType > -void PhaseConstraint< WellConstraintType >::postInputInitialization() +void PhaseVolumeRateConstraint::postInputInitialization() { - // Validate value and table options - WellConstraintType::postInputInitialization(); -} + // Validate table options + WellConstraintBase::postInputInitialization(); -template< typename WellConstraintType > -bool PhaseConstraint< WellConstraintType >::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const -{ - return this->isViolated( currentConstraint.phaseVolumeRates()[this->m_phaseIndex], this->getConstraintValue( currentTime )); -} + // check constraint value + GEOS_THROW_IF( m_constraintValue < 0, + getWrapperDataContext( viewKeyStruct::phaseRateString() ) << ": Target value is negative", + InputError ); -namespace -{ -typedef PhaseConstraint< InjectionConstraint > PhaseInjectionConstraint; -REGISTER_CATALOG_ENTRY( WellConstraintBase, PhaseInjectionConstraint, string const &, Group * const ) -typedef PhaseConstraint< ProductionConstraint > PhaseProductionConstraint; -REGISTER_CATALOG_ENTRY( WellConstraintBase, PhaseProductionConstraint, string const &, Group * const ) + GEOS_THROW_IF ((m_constraintValue <= 0.0 && m_constraintScheduleTableName.empty()), + getName() << " " << getDataContext() << ": You need to specify a phase rate constraint. \n" << + "The rate constraint can be specified using " << + "either " << viewKeyStruct::phaseRateString() << + " or " << WellConstraintBase::viewKeyStruct::constraintScheduleTableNameString(), + InputError ); +} +bool PhaseVolumeRateConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const +{ + real64 const currentValue = currentConstraint.phaseVolumeRates()[m_phaseIndex]; + real64 const constraintValue = getConstraintValue( currentTime ); + if( m_rateSign < 0.0 ) + { + return currentValue < constraintValue; + } + else + { + return currentValue > constraintValue; + } } -// Explicit template instantiations to ensure constructors are emitted for registration -template class PhaseConstraint< InjectionConstraint >; -template class PhaseConstraint< ProductionConstraint >; } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.hpp similarity index 76% rename from src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp rename to src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.hpp index 3345882e6e8..a98daba827e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.hpp @@ -14,12 +14,12 @@ */ /* - * @file WellPhaseRateConstraints.hpp + * @file WellPhaseVolumeRateConstraint.hpp */ -#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLPHASERATECONSTRAINTS_HPP -#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLPHASERATECONSTRAINTS_HPP +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLPHASEVOLUMERATECONSTRAINT_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLPHASEVOLUMERATECONSTRAINT_HPP #include "common/format/EnumStrings.hpp" #include "dataRepository/Group.hpp" @@ -47,11 +47,11 @@ localIndex getPhaseIndexFromFluidModel( T const & fluidModel, std::string const }; /** - * @class PhaseConstraint + * @class PhaseVolumeRateConstraint * @brief This class describes a phase rate constraint used to control a well of WellConstraintType type (Injection or Production). */ -template< typename WellConstraintType > -class PhaseConstraint : public WellConstraintType + +class PhaseVolumeRateConstraint : public WellConstraintBase { public: @@ -66,39 +66,39 @@ class PhaseConstraint : public WellConstraintType * @param[in] name the name of this instantiation of WellControls in the repository * @param[in] parent the parent group of this instantiation of WellControls */ - explicit PhaseConstraint( string const & name, dataRepository::Group * const parent ); + explicit PhaseVolumeRateConstraint( string const & name, dataRepository::Group * const parent ); /** * @brief Default destructor. */ - ~PhaseConstraint() override; + ~PhaseVolumeRateConstraint() override; /** * @brief Deleted default constructor. */ - PhaseConstraint() = delete; + PhaseVolumeRateConstraint() = delete; /** * @brief Deleted copy constructor. */ - PhaseConstraint( PhaseConstraint const & ) = delete; + PhaseVolumeRateConstraint( PhaseVolumeRateConstraint const & ) = delete; /** * @brief Deleted move constructor. */ - PhaseConstraint( PhaseConstraint && ) = delete; + PhaseVolumeRateConstraint( PhaseVolumeRateConstraint && ) = delete; /** * @brief Deleted assignment operator. * @return a reference to a constraint object */ - PhaseConstraint & operator=( PhaseConstraint const & ) = delete; + PhaseVolumeRateConstraint & operator=( PhaseVolumeRateConstraint const & ) = delete; /** * @brief Deleted move operator. * @return a reference to a constraint object */ - PhaseConstraint & operator=( PhaseConstraint && ) = delete; + PhaseVolumeRateConstraint & operator=( PhaseVolumeRateConstraint && ) = delete; ///@} @@ -108,14 +108,7 @@ class PhaseConstraint : public WellConstraintType */ static string catalogName() { - if constexpr ( std::is_same_v< WellConstraintType, InjectionConstraint > ) // special case - { - return "PhaseInjectionConstraint"; - } - else // default - { - return "PhaseProductionConstraint"; - } + return "PhaseVolumeRateConstraint"; } /** @@ -169,19 +162,18 @@ class PhaseConstraint : public WellConstraintType }; -template< typename WellConstraintType > template< typename T > -void PhaseConstraint< WellConstraintType >::validatePhaseType( T const & fluidModel ) +void PhaseVolumeRateConstraint::validatePhaseType( T const & fluidModel ) { // Find target phase index for phase rate constraint m_phaseIndex = getPhaseIndexFromFluidModel( fluidModel, this->template getReference< string >( viewKeyStruct::phaseNameString())); GEOS_THROW_IF( m_phaseIndex == -1, - "PhaseConstraint " << this->template getReference< string >( viewKeyStruct::phaseNameString()) << + "PhaseVolumeRateConstraint " << this->template getReference< string >( viewKeyStruct::phaseNameString()) << ": Invalid phase type for simulation fluid model", InputError ); } } //namespace geos -#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINT_HPP +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLPHASEVOLUMERATECONSTRAINT_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellProductionConstraint.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellProductionConstraint.cpp new file mode 100644 index 00000000000..ce0a26f49b3 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellProductionConstraint.cpp @@ -0,0 +1,69 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellProductionConstraint.cpp + */ + +#include "LogLevelsInfo.hpp" +#include "WellProductionConstraint.hpp" +#include "WellConstants.hpp" +#include "dataRepository/InputFlags.hpp" +#include "functions/FunctionManager.hpp" + +#include "WellLiquidRateConstraint.hpp" +#include "WellMassRateConstraint.hpp" +#include "WellPhaseVolumeRateConstraint.hpp" +#include "WellVolumeRateConstraint.hpp" + +namespace geos +{ + +template< typename ConstraintRateType > +ProductionConstraint< ConstraintRateType >::ProductionConstraint( string const & name, Group * const parent ) + : ConstraintRateType( name, parent ) +{ + // set rate sign for producers (base class member) + this->m_rateSign = -1.0; +} +template< typename ConstraintRateType > +ProductionConstraint< ConstraintRateType >::~ProductionConstraint() +{} + +template< typename ConstraintRateType > +void ProductionConstraint< ConstraintRateType >::postInputInitialization() +{ + // Validate value and table options + ConstraintRateType::postInputInitialization(); + +} +// Register concrete wrapper constraint types and instantiate templates. + +using LiquidProductionConstraint = ProductionConstraint< LiquidRateConstraint >; +REGISTER_CATALOG_ENTRY( WellConstraintBase, LiquidProductionConstraint, string const &, Group * const ) +template class ProductionConstraint< LiquidRateConstraint >; + +using MassProductionConstraint = ProductionConstraint< MassRateConstraint >; +REGISTER_CATALOG_ENTRY( WellConstraintBase, MassProductionConstraint, string const &, Group * const ) +template class ProductionConstraint< MassRateConstraint >; + +using PhaseProductionConstraint = ProductionConstraint< PhaseVolumeRateConstraint >; +REGISTER_CATALOG_ENTRY( WellConstraintBase, PhaseProductionConstraint, string const &, Group * const ) +template class ProductionConstraint< PhaseVolumeRateConstraint >; + +using TotalVolProductionConstraint = ProductionConstraint< VolumeRateConstraint >; +REGISTER_CATALOG_ENTRY( WellConstraintBase, TotalVolProductionConstraint, string const &, Group * const ) +template class ProductionConstraint< VolumeRateConstraint >; +} //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellProductionConstraint.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellProductionConstraint.hpp new file mode 100644 index 00000000000..ee8e8bbe031 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellProductionConstraint.hpp @@ -0,0 +1,105 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellProductionConstraints.hpp + */ + + +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLPRODUCTIONCONSTRAINT_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLPRODUCTIONCONSTRAINT_HPP + +#include "common/format/EnumStrings.hpp" +#include "dataRepository/Group.hpp" +#include "functions/TableFunction.hpp" + +namespace geos +{ +using namespace dataRepository; +/** + * @class ProductionConstraint + * @brief This class describes constraint used to control a production well. + */ + +template< typename ConstraintType > +class ProductionConstraint : public ConstraintType +{ +public: + /** + * @name Constructor / Destructor + */ + ///@{ + + /** + * @brief Constructor for WellControls Objects. + * @param[in] name the name of this instantiation of WellControls in the repository + * @param[in] parent the parent group of this instantiation of WellControls + */ + explicit ProductionConstraint( string const & name, dataRepository::Group * const parent ); + + /** + * @brief Default destructor. + */ + ~ProductionConstraint() override; + + /** + * @brief Deleted default constructor. + */ + ProductionConstraint() = delete; + + /** + * @brief Deleted copy constructor. + */ + ProductionConstraint( ProductionConstraint const & ) = delete; + + /** + * @brief Deleted move constructor. + */ + ProductionConstraint( ProductionConstraint && ) = delete; + + /** + * @brief Deleted assignment operator. + * @return a reference to a constraint object + */ + ProductionConstraint & operator=( ProductionConstraint const & ) = delete; + + /** + * @brief Deleted move operator. + * @return a reference to a constraint object + */ + ProductionConstraint & operator=( ProductionConstraint && ) = delete; + + ///@} + + /** + * @brief name of the node manager in the object catalog + * @return string that contains the catalog name to generate a new Constraint object through the object catalog. + */ + static string catalogName() + { + return "ProductionConstraint"+ConstraintType::catalogName(); + } +protected: + + virtual void postInputInitialization() override; + + static bool isViolated( const real64 & currentValue, const real64 & constraintValue ) + { return currentValue < constraintValue; } +}; + + +} //namespace geos + +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLPRODUCTIONCONSTRAINT_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.cpp deleted file mode 100644 index 167b6467864..00000000000 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * SPDX-License-Identifier: LGPL-2.1-only - * - * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 TotalEnergies - * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University - * Copyright (c) 2023-2024 Chevron - * Copyright (c) 2019- GEOS/GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/* - * @file WellTotalVolRateConstraints.cpp - */ - -#include "LogLevelsInfo.hpp" -#include "WellTotalVolRateConstraints.hpp" -#include "WellConstants.hpp" -#include "dataRepository/InputFlags.hpp" -#include "functions/FunctionManager.hpp" - - -namespace geos -{ - -using namespace dataRepository; - -template< typename WellConstraintType > -TotalVolConstraint< WellConstraintType >::TotalVolConstraint( string const & name, Group * const parent ) - : WellConstraintType( name, parent ) -{ - this->setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); - - this->registerWrapper( viewKeyStruct::volumeRateString(), &this->m_constraintValue ). - setDefaultValue( 0.0 ). - setInputFlag( InputFlags::OPTIONAL ). - setRestartFlags( RestartFlags::WRITE_AND_READ ). - setDescription( "Volumetric rate (if useSurfaceConditions: [surface m^3/s]; else [reservoir m^3/s])" ); - -} - -template< typename WellConstraintType > -TotalVolConstraint< WellConstraintType >::~TotalVolConstraint() -{} - -template< typename WellConstraintType > -void TotalVolConstraint< WellConstraintType >::postInputInitialization() -{ - WellConstraintBase::postInputInitialization(); -} - -template< typename WellConstraintType > -bool TotalVolConstraint< WellConstraintType >::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime )const -{ - return WellConstraintType::isViolated( currentConstraint.totalVolumeRate(), this->getConstraintValue( currentTime )); -} - -typedef TotalVolConstraint< InjectionConstraint > TotalVolInjectionConstraint; -REGISTER_CATALOG_ENTRY( WellConstraintBase, TotalVolInjectionConstraint, string const &, Group * const ) -typedef TotalVolConstraint< ProductionConstraint > TotalVolProductionConstraint; -REGISTER_CATALOG_ENTRY( WellConstraintBase, TotalVolProductionConstraint, string const &, Group * const ) - - -// Explicit template instantiations to ensure constructors are emitted for registration -template class TotalVolConstraint< InjectionConstraint >; -template class TotalVolConstraint< ProductionConstraint >; - -} //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellVolumeRateConstraint.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellVolumeRateConstraint.cpp new file mode 100644 index 00000000000..db11dd85ef2 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellVolumeRateConstraint.cpp @@ -0,0 +1,80 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/* + * @file WellVolumeRateConstraint.cpp + */ + +#include "LogLevelsInfo.hpp" +#include "WellVolumeRateConstraint.hpp" +#include "WellConstants.hpp" +#include "dataRepository/InputFlags.hpp" +#include "functions/FunctionManager.hpp" + +namespace geos +{ + +using namespace dataRepository; + +VolumeRateConstraint::VolumeRateConstraint( string const & name, Group * const parent ) + : WellConstraintBase( name, parent ) +{ + this->setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); + + this->registerWrapper( viewKeyStruct::volumeRateString(), &this->m_constraintValue ). + setDefaultValue( 0.0 ). + setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::WRITE_AND_READ ). + setDescription( "Volumetric rate (if useSurfaceConditions: [surface m^3/s]; else [reservoir m^3/s])" ); + +} + +VolumeRateConstraint::~VolumeRateConstraint() +{} + + +void VolumeRateConstraint::postInputInitialization() +{ + // Validate table options + WellConstraintBase::postInputInitialization(); + + // check constraint value + GEOS_THROW_IF( m_constraintValue < 0, + getWrapperDataContext( viewKeyStruct::volumeRateString() ) << ": Target value is negative", + InputError ); + + GEOS_THROW_IF ((m_constraintValue <= 0.0 && m_constraintScheduleTableName.empty()), + getName() << " " << getDataContext() << ": You need to specify a volume rate constraint. \n" << + "The rate constraint can be specified using " << + "either " << viewKeyStruct::volumeRateString() << + " or " << WellConstraintBase::viewKeyStruct::constraintScheduleTableNameString(), + InputError ); +} + +bool VolumeRateConstraint::checkViolation( WellConstraintBase const & currentConstraint, real64 const & currentTime ) const +{ + real64 const currentValue = currentConstraint.totalVolumeRate(); + real64 const constraintValue = this->getConstraintValue( currentTime ); + if( this->m_rateSign < 0.0 ) + { + return currentValue < constraintValue; + } + else + { + return currentValue > constraintValue; + } +} + +} //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellVolumeRateConstraint.hpp similarity index 78% rename from src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp rename to src/coreComponents/physicsSolvers/fluidFlow/wells/WellVolumeRateConstraint.hpp index 3e7dc4a5e27..1ed14597ca3 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellVolumeRateConstraint.hpp @@ -31,11 +31,11 @@ namespace geos /** - * @class TotalVolConstraint + * @class VolumeRateConstraint * @brief This class describes a volume rate constraint used to control a well. */ -template< typename WellConstraintType > -class TotalVolConstraint : public WellConstraintType + +class VolumeRateConstraint : public WellConstraintBase { public: @@ -49,40 +49,40 @@ class TotalVolConstraint : public WellConstraintType * @param[in] name the name of this instantiation of WellControls in the repository * @param[in] parent the parent group of this instantiation of WellControls */ - explicit TotalVolConstraint( string const & name, dataRepository::Group * const parent ); + explicit VolumeRateConstraint( string const & name, dataRepository::Group * const parent ); /** * @brief Default destructor. */ - ~TotalVolConstraint() override; + ~VolumeRateConstraint() override; /** * @brief Deleted default constructor. */ - TotalVolConstraint() = delete; + VolumeRateConstraint() = delete; /** * @brief Deleted copy constructor. */ - TotalVolConstraint( TotalVolConstraint const & ) = delete; + VolumeRateConstraint( VolumeRateConstraint const & ) = delete; /** * @brief Deleted move constructor. */ - TotalVolConstraint( TotalVolConstraint && ) = delete; + VolumeRateConstraint( VolumeRateConstraint && ) = delete; /** * @brief Deleted assignment operator. * @return a reference to a constraint object */ - TotalVolConstraint & operator=( TotalVolConstraint const & ) = delete; + VolumeRateConstraint & operator=( VolumeRateConstraint const & ) = delete; /** * @brief Deleted move operator. * @return a reference to a constraint object */ - TotalVolConstraint & operator=( TotalVolConstraint && ) = delete; + VolumeRateConstraint & operator=( VolumeRateConstraint && ) = delete; /** * @brief name of the node manager in the object catalog @@ -90,14 +90,7 @@ class TotalVolConstraint : public WellConstraintType */ static string catalogName() { - if constexpr ( std::is_same_v< WellConstraintType, InjectionConstraint > ) // special case - { - return "TotalVolInjectionConstraint"; - } - else // default - { - return "TotalVolProductionConstraint"; - } + return "VolumeRateConstraint"; } ///@} /** diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/WellConstraintKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellConstraintKernels.hpp similarity index 96% rename from src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/WellConstraintKernels.hpp rename to src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellConstraintKernels.hpp index f9a19cba38b..485545cd2d9 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/WellConstraintKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellConstraintKernels.hpp @@ -14,7 +14,7 @@ */ /** - * @file WellConstraintKernels.hpp + * @file CompositionalMultiphaseWellConstraintKernels.hpp */ #ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONSTRAINTKERNELS_HPP @@ -27,10 +27,10 @@ #include "physicsSolvers/fluidFlow/wells/WellControls.hpp" #include "physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp" -#include "physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp" -#include "physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp" -#include "physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp" -#include "physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellVolumeRateConstraint.hpp" +#include "physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.hpp" +#include "physicsSolvers/fluidFlow/wells/WellMassRateConstraint.hpp" +#include "physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.hpp" namespace geos { @@ -117,10 +117,10 @@ struct ConstraintHelper } - template< typename T > + template< template< typename U > class T, typename U=PhaseVolumeRateConstraint > static void assembleConstraintEquation( real64 const & time_n, WellControls & wellControls, - PhaseConstraint< T > & constraint, + T< PhaseVolumeRateConstraint > & constraint, WellElementSubRegion const & subRegion, string const & wellDofKey, localIndex const & rankOffset, @@ -224,10 +224,10 @@ struct ConstraintHelper COFFSET_WJ::nDer ); } - template< typename T > + template< template< typename U > class T, typename U=LiquidRateConstraint > static void assembleConstraintEquation( real64 const & time_n, WellControls & wellControls, - LiquidConstraint< T > & constraint, + T< LiquidRateConstraint > & constraint, WellElementSubRegion const & subRegion, string const & wellDofKey, localIndex const & rankOffset, @@ -341,10 +341,10 @@ struct ConstraintHelper dControlEqn, COFFSET_WJ::nDer ); } - template< typename T > + template< template< typename U > class T, typename U=VolumeRateConstraint > static void assembleConstraintEquation( real64 const & time_n, WellControls & wellControls, - TotalVolConstraint< T > & constraint, + T< VolumeRateConstraint > & constraint, WellElementSubRegion const & subRegion, string const & wellDofKey, localIndex const & rankOffset, @@ -441,10 +441,10 @@ struct ConstraintHelper dControlEqn, COFFSET_WJ::nDer ); } - template< typename T > + template< template< typename U > class T, typename U=MassRateConstraint > static void assembleConstraintEquation( real64 const & time_n, WellControls & wellControls, - MassConstraint< T > & constraint, + T< MassRateConstraint > & constraint, WellElementSubRegion const & subRegion, string const & wellDofKey, localIndex const & rankOffset, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp index 962562d26f6..0a78824d6e9 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp @@ -650,7 +650,7 @@ RateInitializationKernel:: ConstraintTypeId const controlType = constraints[0]->getControl(); if( controlType == ConstraintTypeId::PHASEVOLRATE ) { - integer const targetPhaseIndex = dynamic_cast< const PhaseConstraint< ProductionConstraint > * >( constraints[0] )->getPhaseIndex(); + integer const targetPhaseIndex = wellControls.getConstraintPhaseIndex(); forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) { @@ -680,7 +680,7 @@ RateInitializationKernel:: ConstraintTypeId const controlType = constraints[0]->getControl(); if( controlType == ConstraintTypeId::PHASEVOLRATE ) { - integer const targetPhaseIndex = dynamic_cast< const PhaseConstraint< InjectionConstraint > * >( constraints[0] )->getPhaseIndex(); + integer const targetPhaseIndex = wellControls.getConstraintPhaseIndex(); forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp index 30fc875f85c..b01d8adf0ab 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp @@ -40,7 +40,7 @@ #include "physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWellFields.hpp" #include "physicsSolvers/fluidFlow/wells/WellControls.hpp" #include "physicsSolvers/fluidFlow/wells/WellSolverBaseFields.hpp" -#include "physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.hpp" namespace geos { @@ -530,7 +530,7 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa // This is a normalizer for the balance equations. The normalizaer should be the current rate not the constraint value!! // This is one of the reasons for restricting constraint type for a production well // another pr will remove fix this (so the cause for difference results is isolated to one change) - m_targetPhaseIndex = dynamic_cast< PhaseConstraint< ProductionConstraint > * >(wellControls.getProdRateConstraints()[0])->getPhaseIndex( ); + m_targetPhaseIndex = wellControls.getConstraintPhaseIndex( ); m_constraintValue = wellControls.getProdRateConstraints()[0]->getConstraintValue( time ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellConstraintKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellConstraintKernels.hpp index b6876111ca0..a7f7af725ce 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellConstraintKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellConstraintKernels.hpp @@ -27,10 +27,9 @@ #include "physicsSolvers/fluidFlow/wells/WellControls.hpp" #include "physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp" -#include "physicsSolvers/fluidFlow/wells/WellTotalVolRateConstraints.hpp" -#include "physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp" -#include "physicsSolvers/fluidFlow/wells/WellMassRateConstraints.hpp" -#include "physicsSolvers/fluidFlow/wells/WellLiquidRateConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellVolumeRateConstraint.hpp" + + namespace geos { @@ -112,10 +111,10 @@ struct ConstraintHelper dControlEqn, COFFSET_WJ::nDer ); } - template< typename T > + template< template< typename U > class T, typename U=VolumeRateConstraint > static void assembleConstraintEquation( real64 const & time_n, WellControls & wellControls, - TotalVolConstraint< T > & constraint, + T< VolumeRateConstraint > & constraint, WellElementSubRegion const & subRegion, string const & wellDofKey, localIndex const & rankOffset, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.cpp index ebd6ee4c657..b7b32a0ecfe 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.cpp @@ -23,6 +23,7 @@ #include "physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp" #include "physicsSolvers/fluidFlow/wells/SinglePhaseWellFields.hpp" #include "constitutive/fluid/singlefluid/SingleFluidLayouts.hpp" + namespace geos { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.hpp index 80a471e22d9..dcb8b61f9be 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.hpp @@ -20,18 +20,21 @@ #ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_SINGLEPHASEWELLKERNELS_HPP #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_SINGLEPHASEWELLKERNELS_HPP +#include "common/DataTypes.hpp" +#include "common/GEOS_RAJA_Interface.hpp" +#include "physicsSolvers/PhysicsSolverBaseKernels.hpp" + #include "constitutive/fluid/singlefluid/SingleFluidFields.hpp" #include "constitutive/fluid/singlefluid/SingleFluidBase.hpp" #include "constitutive/fluid/singlefluid/SingleFluidLayouts.hpp" #include "constitutive/fluid/singlefluid/SingleFluidLayouts.hpp" -#include "common/DataTypes.hpp" -#include "common/GEOS_RAJA_Interface.hpp" + #include "mesh/ElementRegionManager.hpp" #include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" #include "physicsSolvers/fluidFlow/StencilAccessors.hpp" #include "physicsSolvers/fluidFlow/wells/WellControls.hpp" #include "physicsSolvers/fluidFlow/wells/SinglePhaseWellFields.hpp" -#include "physicsSolvers/PhysicsSolverBaseKernels.hpp" + #include "physicsSolvers/KernelLaunchSelectors.hpp" namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp index cf192b1e8aa..a949203843a 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp @@ -23,7 +23,7 @@ #include "physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp" #include "physicsSolvers/PhysicsSolverBaseKernels.hpp" #include "physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp" -#include "physicsSolvers/fluidFlow/wells/WellPhaseRateConstraints.hpp" +#include "physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.hpp" namespace geos { @@ -190,10 +190,11 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa { if( m_isProducer ) { + // tjb This needs to be fixed should use current constraint rate for normalization m_targetBHP = wellControls.getMinBHPConstraint()->getConstraintValue( time ); if( m_currentControl == WellControls::Control::PHASEVOLRATE ) { - m_targetPhaseIndex = dynamic_cast< const PhaseConstraint< ProductionConstraint > * >( wellControls.getCurrentConstraint() )->getPhaseIndex(); + m_targetPhaseIndex = wellControls.getConstraintPhaseIndex(); } } else @@ -201,7 +202,7 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa m_targetBHP = wellControls.getMaxBHPConstraint()->getConstraintValue( time ); if( m_currentControl == WellControls::Control::PHASEVOLRATE ) { - m_targetPhaseIndex = dynamic_cast< const PhaseConstraint< InjectionConstraint > * >( wellControls.getCurrentConstraint() )->getPhaseIndex(); + m_targetPhaseIndex = wellControls.getConstraintPhaseIndex(); } } @@ -658,8 +659,7 @@ class ElementBasedAssemblyKernelFactory CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - isothermalCompositionalMultiphaseBaseKernels:: - internal::kernelLaunchSelectorCompSwitch( numComps, [&]( auto NC ) + isothermalCompositionalMultiphaseBaseKernels::internal::kernelLaunchSelectorCompSwitch( numComps, [&]( auto NC ) { localIndex constexpr NUM_COMP = NC(); From b6ae5ef82448c1a6eb0dc0428e99942677ec75a9 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Mon, 13 Oct 2025 13:08:03 -0700 Subject: [PATCH 11/71] fix reference to 'internal' is ambiguous error --- src/coreComponents/linearAlgebra/utilities/ComponentMask.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreComponents/linearAlgebra/utilities/ComponentMask.hpp b/src/coreComponents/linearAlgebra/utilities/ComponentMask.hpp index a27d1a37a64..42eab7c568e 100644 --- a/src/coreComponents/linearAlgebra/utilities/ComponentMask.hpp +++ b/src/coreComponents/linearAlgebra/utilities/ComponentMask.hpp @@ -92,10 +92,10 @@ class ComponentMask private: /// Number of bits in mask storage - static constexpr int NUM_BITS = internal::roundToNextPowerOfTwo( MAX_COMP ); + static constexpr int NUM_BITS = geos::internal::roundToNextPowerOfTwo( MAX_COMP ); /// Type used to represent the bit mask - using mask_t = typename internal::ComponentMaskType< NUM_BITS >::type; + using mask_t = typename geos::internal::ComponentMaskType< NUM_BITS >::type; public: From fa61ab139def5ae6ffcc2c4e861a7681c767bc15 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 14 Oct 2025 06:47:30 -0700 Subject: [PATCH 12/71] 1) well constraint schema script, 2) converted xmls, 3) Failed convert compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml --- .../1D_100cells/1D_benchmark.xml | 688 +++++++++-------- .../soreideWhitson/1D_100cells/1D_smoke.xml | 688 +++++++++-------- .../class09_pb3_drainageOnly_direct_base.xml | 324 ++++---- ...lass09_pb3_drainageOnly_iterative_base.xml | 421 ++++++----- .../class09_pb3_hystRelperm_direct_base.xml | 347 ++++----- ...class09_pb3_hystRelperm_iterative_base.xml | 364 ++++----- .../benchmarks/Egg/deadOilEgg_base_direct.xml | 688 +++++++++-------- .../Egg/deadOilEgg_base_iterative.xml | 692 ++++++++++-------- .../black_oil_wells_saturated_3d.xml | 475 ++++++------ .../black_oil_wells_saturated_3d_stone2.xml | 488 ++++++------ .../black_oil_wells_unsaturated_3d.xml | 405 +++++----- .../black_oil_wells_unsaturated_3d_stone2.xml | 525 ++++++------- .../compositional_multiphase_wells_1d.xml | 354 ++++----- .../compositional_multiphase_wells_2d.xml | 433 +++++------ .../dead_oil_wells_2d.xml | 468 ++++++------ .../dead_oil_wells_hybrid_2d.xml | 438 +++++------ .../isothm_mass_inj_table.xml | 349 ++++----- .../isothm_vol_inj_table.xml | 360 ++++----- .../simpleCo2InjTutorial_base.xml | 334 ++++----- .../staged_perf_base.xml | 285 ++++---- .../staircase_co2_wells_3d.xml | 398 +++++----- .../staircase_co2_wells_hybrid_3d.xml | 347 ++++----- .../PoroElastic_staircase_co2_3d_fim.xml | 247 ++++--- ...oroElastic_staircase_co2_3d_sequential.xml | 254 ++++--- scripts/convert_well_schema.py | 208 ++++++ 25 files changed, 5589 insertions(+), 4991 deletions(-) create mode 100644 scripts/convert_well_schema.py diff --git a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml index 89b9cc7dc86..407ed2ab5e4 100644 --- a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml +++ b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml @@ -1,294 +1,396 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml index 19a577bde98..4c97d038692 100644 --- a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml +++ b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml @@ -1,294 +1,396 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_direct_base.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_direct_base.xml index f2c31503e8a..36005f1a47a 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_direct_base.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_direct_base.xml @@ -1,201 +1,207 @@ - - - - + name="coupledFlowAndWells" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + initialDt="1e2" + targetRegions="{reservoir, wellRegion}"> + newtonTol="1.0e-3" + newtonMaxIter="12"> + + directParallel="0"> + - - + name="compositionalMultiphaseFlow" + targetRegions="{reservoir}" + discretization="fluidTPFA" + temperature="363" + maxCompFractionChange="0.2" + logLevel="1" + useMass="1"> + + name="compositionalMultiphaseWell" + targetRegions="{wellRegion}" + logLevel="1" + useMass="1" + writeCSV="1"> + name="wellControls" + type="injector" + enableCrossflow="0" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71"> + + + + + - - + name="reservoir" + cellBlocks="{*}" + materialList="{fluid, rock, relperm, cappres}"> + + name="wellRegion" + materialList="{fluid}"> + - + name="fluidTPFA"> + - - + name="fluid" + phaseNames="{gas, water}" + componentNames="{co2, water}" + componentMolarWeight="{44e-3, 18e-3}" + phasePVTParaFiles="{tables/pvtgas.txt, tables/pvtliquid_ez.txt}" + flashModelParaFile="tables/co2flash.txt"> + + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + + name="nullSolid"> + + name="rockPorosity" + defaultReferencePorosity="0.1" + referencePressure="1.0e7" + compressibility="4.5e-10"> + - + name="rockPerm" + permeabilityComponents="{1.0e-12, 1.0e-12, 1.0e-12}"> + - + name="relperm" + phaseNames="{gas, water}" + wettingNonWettingRelPermTableNames="{waterRelativePermeabilityTable, gasRelativePermeabilityTable}"> + + name="cappres" + phaseNames="{gas, water}" + wettingNonWettingCapPressureTableName="waterCapillaryPressureTable"> + - - - - + + + name="bcPressure" + objectPath="faceManager" + setNames="{xpos, xneg, ypos, yneg}" + fieldName="pressure" + functionName="pressureFunction" + scale="1"> + + name="bcTemperature" + objectPath="faceManager" + setNames="{xpos, xneg, ypos, yneg}" + fieldName="temperature" + functionName="temperatureFunction" + scale="1"> + + name="bcCompositionCO2" + objectPath="faceManager" + setNames="{xpos, xneg, ypos, yneg}" + fieldName="globalCompFraction" + component="0" + scale="0.000001"> + - + name="bcCompositionWater" + objectPath="faceManager" + setNames="{xpos, xneg, ypos, yneg}" + fieldName="globalCompFraction" + component="1" + scale="0.999999"> + - + name="initCO2CompFracTable" + coordinates="{-3238.2, -2506.13}" + values="{0.000001, 0.000001}"> + - - + name="initWaterCompFracTable" + coordinates="{-3238.2, -2506.13}" + values="{0.999999, 0.999999}"> + + name="initTempTable" + coordinates="{-3238.2, -2506.13}" + values="{380.296, 358.334}"> + - - - - - - - + name="waterRelativePermeabilityTable" + coordinateFiles="{tables/phaseVolumeFraction_water.txt}" + voxelFile="tables/relPerm_water.txt"> + - + name="gasRelativePermeabilityTable" + coordinateFiles="{tables/phaseVolumeFraction_gas.txt}" + voxelFile="tables/relPerm_gas.txt"> + + + + + + + + + - - + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_iterative_base.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_iterative_base.xml index 8e76b08905b..e0eabc6d0da 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_iterative_base.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_iterative_base.xml @@ -1,259 +1,252 @@ - - - - - + name="coupledFlowAndWells" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + initialDt="1e2" + targetRegions="{reservoir, wellRegion}"> + newtonTol="1.0e-5" + newtonMaxIter="40"> + + solverType="fgmres" + preconditionerType="mgr" + krylovTol="1e-6" + logLevel="1"> + - - - - - - + name="compositionalMultiphaseFlow" + targetRegions="{reservoir}" + discretization="fluidTPFA" + temperature="363" + maxCompFractionChange="0.2" + logLevel="1" + useMass="1"> + - + useMass="1" + writeCSV="1"> + name="wellControls" + logLevel="1" + type="injector" + enableCrossflow="0" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71"> + + + + + + name="MAX_MASS_INJ" + logLevel="1" + type="injector" + enableCrossflow="0" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71" + targetMassRate="15" + injectionTemperature="353.15" + injectionStream="{1.0, 0.0}"> + + + + + + + - - - - + name="reservoir" + cellBlocks="{*}" + materialList="{fluid, rock, relperm, cappres}"> + + name="wellRegion" + materialList="{fluid}"> + - - + name="fluidTPFA"> + - - - - - + name="fluid" + phaseNames="{gas, water}" + componentNames="{co2, water}" + componentMolarWeight="{44e-3, 18e-3}" + phasePVTParaFiles="{tables/pvtgas.txt, tables/pvtliquid_ez.txt}" + flashModelParaFile="tables/co2flash.txt"> + + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + + name="nullSolid"> + + name="rockPorosity" + defaultReferencePorosity="0.1" + referencePressure="1.0e7" + compressibility="4.5e-10"> + - - - + name="rockPerm" + permeabilityComponents="{1.0e-12, 1.0e-12, 1.0e-12}"> + - - - + name="relperm" + phaseNames="{gas, water}" + wettingNonWettingRelPermTableNames="{waterRelativePermeabilityTable, gasRelativePermeabilityTable}"> + - + name="cappres" + phaseNames="{gas, water}" + wettingNonWettingCapPressureTableName="waterCapillaryPressureTable"> + - - - - - - - - + + + name="bcPressure" + objectPath="faceManager" + setNames="{3}" + fieldName="pressure" + functionName="pressureFunction" + scale="1"> + + name="bcTemperature" + objectPath="faceManager" + setNames="{3}" + fieldName="temperature" + functionName="temperatureFunction" + scale="1"> + + name="bcCompositionCO2" + objectPath="faceManager" + setNames="{3}" + fieldName="globalCompFraction" + component="0" + scale="0.000001"> + - + name="bcCompositionWater" + objectPath="faceManager" + setNames="{3}" + fieldName="globalCompFraction" + component="1" + scale="0.999999"> + - + name="initCO2CompFracTable" + coordinates="{-3238.2, -2506.13}" + values="{0.000001, 0.000001}"> + + + + + + + + + - - + name="waterCapillaryPressureTable" + coordinateFiles="{tables/phaseVolumeFraction_water.txt}" + voxelFile="tables/capPres_water.txt"> + + name="temperatureFunction" + inputVarNames="{faceCenter}" + coordinateFiles="{fc_tables/xlin.geos, fc_tables/ylin.geos, fc_tables/zlin.geos}" + voxelFile="fc_tables/temperature.geos" + interpolation="linear"> + - - - - - - - + name="pressureFunction" + inputVarNames="{faceCenter}" + coordinateFiles="{fc_tables/xlin.geos, fc_tables/ylin.geos, fc_tables/zlin.geos}" + voxelFile="fc_tables/pressure.geos" + interpolation="linear"> + - + name="totalRateTable" + inputVarNames="{time}" + coordinates="{0, 7.7198e8, 1.544e9}" + values="{8.02849025, 0, 0}" + interpolation="lower"> + + name="totalMassTable" + inputVarNames="{time}" + coordinates="{0, 7.7198e8, 1.544e9}" + values="{15, 0, 0}" + interpolation="lower"> + - - + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_direct_base.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_direct_base.xml index c731abcf696..0d1f7ddccb3 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_direct_base.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_direct_base.xml @@ -1,215 +1,220 @@ - - - - + name="coupledFlowAndWells" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + initialDt="1e2" + targetRegions="{reservoir, wellRegion}"> + newtonTol="1.0e-3" + newtonMaxIter="12"> + + directParallel="0"> + - - + name="compositionalMultiphaseFlow" + targetRegions="{reservoir}" + discretization="fluidTPFA" + temperature="363" + maxCompFractionChange="0.2" + logLevel="1" + useMass="1"> + + name="compositionalMultiphaseWell" + targetRegions="{wellRegion}" + logLevel="1" + useMass="1" + writeCSV="1"> + name="wellControls" + type="injector" + enableCrossflow="0" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71"> + + + + + - - + name="reservoir" + cellBlocks="{*}" + materialList="{fluid, rock, relperm, cappres}"> + + name="wellRegion" + materialList="{fluid}"> + - + name="fluidTPFA"> + - - + name="fluid" + phaseNames="{gas, water}" + componentNames="{co2, water}" + componentMolarWeight="{44e-3, 18e-3}" + phasePVTParaFiles="{tables/pvtgas.txt, tables/pvtliquid_ez.txt}" + flashModelParaFile="tables/co2flash.txt"> + + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + + name="nullSolid"> + + name="rockPorosity" + defaultReferencePorosity="0.1" + referencePressure="1.0e7" + compressibility="4.5e-10"> + - - + name="rockPerm" + permeabilityComponents="{1.0e-12, 1.0e-12, 1.0e-12}"> + - + name="relperm" + phaseNames="{gas, water}" + drainageWettingNonWettingRelPermTableNames="{drainageWaterRelativePermeabilityTable, + drainageGasRelativePermeabilityTable}" + imbibitionNonWettingRelPermTableName="imbibitionGasRelativePermeabilityTable" + imbibitionWettingRelPermTableName="imbibitionWaterRelativePermeabilityTable"> + + name="cappres" + phaseNames="{gas, water}" + wettingNonWettingCapPressureTableName="waterCapillaryPressureTable"> + - - - - - - + + + name="bcPressure" + objectPath="faceManager" + setNames="{xpos, xneg, ypos, yneg}" + fieldName="pressure" + functionName="pressureFunction" + scale="1"> + + name="bcTemperature" + objectPath="faceManager" + setNames="{xpos, xneg, ypos, yneg}" + fieldName="temperature" + functionName="temperatureFunction" + scale="1"> + + name="bcCompositionCO2" + objectPath="faceManager" + setNames="{xpos, xneg, ypos, yneg}" + fieldName="globalCompFraction" + component="0" + scale="0.000001"> + - + name="bcCompositionWater" + objectPath="faceManager" + setNames="{xpos, xneg, ypos, yneg}" + fieldName="globalCompFraction" + component="1" + scale="0.999999"> + - + name="initCO2CompFracTable" + coordinates="{-3238.2, -2506.13}" + values="{0.000001, 0.000001}"> + + name="initWaterCompFracTable" + coordinates="{-3238.2, -2506.13}" + values="{0.999999, 0.999999}"> + - - - - - - - + name="initTempTable" + coordinates="{-3238.2, -2506.13}" + values="{380.296, 358.334}"> + - - - + name="waterCapillaryPressureTable" + coordinateFiles="{tables/phaseVolumeFraction_water.txt}" + voxelFile="tables/capPres_water.txt"> + + name="temperatureFunction" + inputVarNames="{faceCenter}" + coordinateFiles="{fc_tables/xlin.geos, fc_tables/ylin.geos, fc_tables/zlin.geos}" + voxelFile="fc_tables/temperature.geos" + interpolation="linear"> + + name="pressureFunction" + inputVarNames="{faceCenter}" + coordinateFiles="{fc_tables/xlin.geos, fc_tables/ylin.geos, fc_tables/zlin.geos}" + voxelFile="fc_tables/pressure.geos" + interpolation="linear"> + - + name="totalRateTable" + inputVarNames="{time}" + coordinates="{0, 7.7198e8, 1.544e9}" + values="{8.02849025, 0, 0}" + interpolation="lower"> + + + + + + + + + - - + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_iterative_base.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_iterative_base.xml index ee1af0ef88d..bf0e54bfddf 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_iterative_base.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_iterative_base.xml @@ -1,228 +1,234 @@ - - - - + name="coupledFlowAndWells" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + initialDt="1e2" + targetRegions="{reservoir, wellRegion}"> + newtonTol="1.0e-3" + newtonMaxIter="12"> + + solverType="fgmres" + preconditionerType="mgr" + krylovTol="1e-6" + logLevel="1"> + - - + name="compositionalMultiphaseFlow" + targetRegions="{reservoir}" + discretization="fluidTPFA" + temperature="363" + maxCompFractionChange="0.2" + logLevel="1" + useMass="1"> + - + useMass="1" + writeCSV="1"> + + + + + + - - + name="reservoir" + cellBlocks="{*}" + materialList="{fluid, rock, relperm, cappres}"> + + name="wellRegion" + materialList="{fluid}"> + - + name="fluidTPFA"> + - - + name="fluid" + phaseNames="{gas, water}" + componentNames="{co2, water}" + componentMolarWeight="{44e-3, 18e-3}" + phasePVTParaFiles="{tables/pvtgas.txt, tables/pvtliquid_ez.txt}" + flashModelParaFile="tables/co2flash.txt"> + + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + + name="nullSolid"> + + name="rockPorosity" + defaultReferencePorosity="0.1" + referencePressure="1.0e7" + compressibility="4.5e-10"> + - - - + name="rockPerm" + permeabilityComponents="{1.0e-12, 1.0e-12, 1.0e-12}"> + - - + name="relperm" + phaseNames="{gas, water}" + drainageWettingNonWettingRelPermTableNames="{drainageWaterRelativePermeabilityTable, + drainageGasRelativePermeabilityTable}" + imbibitionNonWettingRelPermTableName="imbibitionGasRelativePermeabilityTable" + imbibitionWettingRelPermTableName="imbibitionWaterRelativePermeabilityTable"> + + name="cappres" + phaseNames="{gas, water}" + wettingNonWettingCapPressureTableName="waterCapillaryPressureTable"> + - - - + name="equil" + objectPath="ElementRegions" + datumElevation="-3000" + datumPressure="3.0e7" + initialPhaseName="water" + componentNames="{co2, water}" + componentFractionVsElevationTableNames="{initCO2CompFracTable, initWaterCompFracTable}" + temperatureVsElevationTableName="initTempTable"> + + name="bcPressure" + objectPath="faceManager" + setNames="{3}" + fieldName="pressure" + functionName="pressureFunction" + scale="1"> + + name="bcTemperature" + objectPath="faceManager" + setNames="{3}" + fieldName="temperature" + functionName="temperatureFunction" + scale="1"> + + name="bcCompositionCO2" + objectPath="faceManager" + setNames="{3}" + fieldName="globalCompFraction" + component="0" + scale="0.000001"> + - + name="bcCompositionWater" + objectPath="faceManager" + setNames="{3}" + fieldName="globalCompFraction" + component="1" + scale="0.999999"> + - + name="initCO2CompFracTable" + coordinates="{-3238.2, -2506.13}" + values="{0.000001, 0.000001}"> + + + + + + name="waterRelativePermeabilityTable" + coordinateFiles="{tables/phaseVolumeFraction_water.txt}" + voxelFile="tables/relPerm_water.txt"> + - + name="gasRelativePermeabilityTable" + coordinateFiles="{tables/phaseVolumeFraction_gas.txt}" + voxelFile="tables/relPerm_gas.txt"> + + name="waterCapillaryPressureTable" + coordinateFiles="{tables/phaseVolumeFraction_water.txt}" + voxelFile="tables/capPres_water.txt"> + - + name="temperatureFunction" + inputVarNames="{faceCenter}" + coordinateFiles="{fc_tables/xlin.geos, fc_tables/ylin.geos, fc_tables/zlin.geos}" + voxelFile="fc_tables/temperature.geos" + interpolation="linear"> + - - - - - + name="pressureFunction" + inputVarNames="{faceCenter}" + coordinateFiles="{fc_tables/xlin.geos, fc_tables/ylin.geos, fc_tables/zlin.geos}" + voxelFile="fc_tables/pressure.geos" + interpolation="linear"> + - - + name="totalRateTable" + inputVarNames="{time}" + coordinates="{0, 7.7198e8, 1.544e9}" + values="{8.02849025, 0, 0}" + interpolation="lower"> + + name="drainageWaterRelativePermeabilityTable" + coordinateFiles="{tables/drainagePhaseVolFraction_water.txt}" + voxelFile="tables/drainageRelPerm_water.txt"> + + name="drainageGasRelativePermeabilityTable" + coordinateFiles="{tables/drainagePhaseVolFraction_gas.txt}" + voxelFile="tables/drainageRelPerm_gas.txt"> + + name="imbibitionWaterRelativePermeabilityTable" + coordinateFiles="{tables/imbibitionPhaseVolFraction_water.txt}" + voxelFile="tables/imbibitionRelPerm_water.txt"> + - + name="imbibitionGasRelativePermeabilityTable" + coordinateFiles="{tables/imbibitionPhaseVolFraction_gas.txt}" + voxelFile="tables/imbibitionRelPerm_gas.txt"> + - - + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml index 048e88999d7..ee697474dcf 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml @@ -1,404 +1,448 @@ - - - + name="coupledFlowAndWells" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + initialDt="1e4" + targetRegions="{reservoir, wellRegion1, wellRegion2, wellRegion3, wellRegion4, wellRegion5, + wellRegion6, wellRegion7, wellRegion8, wellRegion9, wellRegion10, wellRegion11, wellRegion12}"> + newtonTol="1.0e-4" + newtonMaxIter="25" + timeStepDecreaseIterLimit="0.9" + timeStepIncreaseIterLimit="0.6" + timeStepCutFactor="0.1" + maxTimeStepCuts="10" + lineSearchAction="None"> + + solverType="direct" + directParallel="0"> + - - + name="compositionalMultiphaseFlow" + targetRegions="{reservoir}" + discretization="fluidTPFA" + temperature="297.15" + targetRelativePressureChangeInTimeStep="1" + targetPhaseVolFractionChangeInTimeStep="1" + maxCompFractionChange="0.3" + logLevel="1" + useMass="1"> + + name="compositionalMultiphaseWell" + targetRegions="{wellRegion1, wellRegion2, wellRegion3, wellRegion4, wellRegion5, wellRegion6, + wellRegion7, wellRegion8, wellRegion9, wellRegion10, wellRegion11, wellRegion12}" + maxCompFractionChange="0.5" + logLevel="1" + useMass="1" + writeCSV="1"> + name="wellControls1" + type="producer"> + + + + + - - - + name="wellControls2" + type="producer"> + + + + + + name="wellControls3" + type="producer"> + + + + + + name="wellControls4" + type="producer"> + + + + + + name="wellControls5" + type="injector"> + + + + + + name="wellControls6" + type="injector"> + + + + + + name="wellControls7" + type="injector"> + + + + + + name="wellControls8" + type="injector"> + + + + + + name="wellControls9" + type="injector"> + + + + + + name="wellControls10" + type="injector"> + + + + + + name="wellControls11" + type="injector"> + + + + + + name="wellControls12" + type="injector"> + + + + + - - + maxTime="1.5e7"> - + name="vtk" + timeFrequency="2e6" + target="/Outputs/vtkOutput"> + - + name="timeHistoryOutput1" + timeFrequency="1.5e7" + target="/Outputs/timeHistoryOutput1"> + - + name="timeHistoryOutput2" + timeFrequency="1.5e7" + target="/Outputs/timeHistoryOutput2"> + - + name="timeHistoryOutput3" + timeFrequency="1.5e7" + target="/Outputs/timeHistoryOutput3"> + - + name="timeHistoryOutput4" + timeFrequency="1.5e7" + target="/Outputs/timeHistoryOutput4"> + - + name="solverApplications" + maxEventDt="5e5" + target="/Solvers/coupledFlowAndWells"> + - + name="timeHistoryCollection1" + timeFrequency="1e6" + target="/Tasks/wellRateCollection1"> + - + name="timeHistoryCollection2" + timeFrequency="1e6" + target="/Tasks/wellRateCollection2"> + - + name="timeHistoryCollection3" + timeFrequency="1e6" + target="/Tasks/wellRateCollection3"> + - + name="timeHistoryCollection4" + timeFrequency="1e6" + target="/Tasks/wellRateCollection4"> + - + name="restarts" + timeFrequency="7.5e6" + targetExactTimestep="0" + target="/Outputs/restartOutput"> + - - - + name="fluidTPFA"> + - - - - + name="reservoir" + cellBlocks="{*}" + materialList="{fluid, rock, relperm}"> + - + name="wellRegion1" + materialList="{fluid}"> + - - - + name="wellRegion2" + materialList="{fluid}"> + - + name="wellRegion3" + materialList="{fluid}"> + - + name="wellRegion4" + materialList="{fluid}"> + - + name="wellRegion5" + materialList="{fluid}"> + - + name="wellRegion6" + materialList="{fluid}"> + - + name="wellRegion7" + materialList="{fluid}"> + - + name="wellRegion8" + materialList="{fluid}"> + - + name="wellRegion9" + materialList="{fluid}"> + - + name="wellRegion10" + materialList="{fluid}"> + - + name="wellRegion11" + materialList="{fluid}"> + + name="wellRegion12" + materialList="{fluid}"> + - - - + name="fluid" + phaseNames="{oil, water}" + surfaceDensities="{848.9, 1025.2}" + componentMolarWeight="{114e-3, 18e-3}" + tableFiles="{pvdo.txt, pvtw.txt}"> + - + name="relperm" + phaseNames="{oil, water}" + phaseMinVolumeFraction="{0.1, 0.2}" + phaseRelPermExponent="{4.0, 3.0}" + phaseRelPermMaxValue="{0.8, 0.75}"> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + - + name="nullSolid"> + - + name="rockPorosity" + defaultReferencePorosity="0.2" + referencePressure="0.0" + compressibility="1.0e-13"> + + name="rockPerm" + permeabilityComponents="{5.0e-13, 5.0e-13, 1.0e-13}"> + - - - - + name="initialPressure" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/reservoir/DEFAULT_HEX" + fieldName="pressure" + scale="4e7"> + - + name="initialComposition_oil" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/reservoir/DEFAULT_HEX" + fieldName="globalCompFraction" + component="0" + scale="0.9"> + + name="initialComposition_water" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/reservoir/DEFAULT_HEX" + fieldName="globalCompFraction" + component="1" + scale="0.1"> + - - - - + name="vtkOutput"> + - + name="timeHistoryOutput1" + sources="{/Tasks/wellRateCollection1}" + filename="wellRateHistory1"> + - + name="timeHistoryOutput2" + sources="{/Tasks/wellRateCollection2}" + filename="wellRateHistory2"> + - + name="timeHistoryOutput3" + sources="{/Tasks/wellRateCollection3}" + filename="wellRateHistory3"> + - + name="timeHistoryOutput4" + sources="{/Tasks/wellRateCollection4}" + filename="wellRateHistory4"> + - + name="restartOutput"> + - - - - + name="wellRateCollection1" + objectPath="ElementRegions/wellRegion1/wellRegion1UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"> + - + name="wellRateCollection2" + objectPath="ElementRegions/wellRegion2/wellRegion2UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"> + - + name="wellRateCollection3" + objectPath="ElementRegions/wellRegion3/wellRegion3UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"> + + name="wellRateCollection4" + objectPath="ElementRegions/wellRegion4/wellRegion4UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"> + - - - + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_iterative.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_iterative.xml index 615688bef78..c7a50898ba1 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_iterative.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_iterative.xml @@ -1,406 +1,450 @@ - - - + name="coupledFlowAndWells" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + initialDt="1e4" + targetRegions="{reservoir, wellRegion1, wellRegion2, wellRegion3, wellRegion4, wellRegion5, + wellRegion6, wellRegion7, wellRegion8, wellRegion9, wellRegion10, wellRegion11, wellRegion12}"> + newtonTol="1.0e-4" + newtonMaxIter="25" + timeStepDecreaseIterLimit="0.9" + timeStepIncreaseIterLimit="0.6" + timeStepCutFactor="0.1" + maxTimeStepCuts="10" + lineSearchAction="None"> + + solverType="fgmres" + preconditionerType="mgr" + krylovTol="1e-4" + krylovAdaptiveTol="1" + krylovWeakestTol="1e-2" + logLevel="1"> + - - + name="compositionalMultiphaseFlow" + targetRegions="{reservoir}" + discretization="fluidTPFA" + temperature="297.15" + maxCompFractionChange="0.3" + logLevel="1" + useMass="1"> + + name="compositionalMultiphaseWell" + targetRegions="{wellRegion1, wellRegion2, wellRegion3, wellRegion4, wellRegion5, wellRegion6, + wellRegion7, wellRegion8, wellRegion9, wellRegion10, wellRegion11, wellRegion12}" + maxCompFractionChange="0.5" + logLevel="1" + useMass="1" + writeCSV="1"> + name="wellControls1" + type="producer"> + + + + + - - - + name="wellControls2" + type="producer"> + + + + + + name="wellControls3" + type="producer"> + + + + + + name="wellControls4" + type="producer"> + + + + + + name="wellControls5" + type="injector"> + + + + + + name="wellControls6" + type="injector"> + + + + + + name="wellControls7" + type="injector"> + + + + + + name="wellControls8" + type="injector"> + + + + + + name="wellControls9" + type="injector"> + + + + + + name="wellControls10" + type="injector"> + + + + + + name="wellControls11" + type="injector"> + + + + + + name="wellControls12" + type="injector"> + + + + + - - + maxTime="1.5e7"> - + name="vtk" + timeFrequency="2e6" + target="/Outputs/vtkOutput"> + - + name="timeHistoryOutput1" + timeFrequency="1.5e7" + target="/Outputs/timeHistoryOutput1"> + - + name="timeHistoryOutput2" + timeFrequency="1.5e7" + target="/Outputs/timeHistoryOutput2"> + - + name="timeHistoryOutput3" + timeFrequency="1.5e7" + target="/Outputs/timeHistoryOutput3"> + - + name="timeHistoryOutput4" + timeFrequency="1.5e7" + target="/Outputs/timeHistoryOutput4"> + - + name="solverApplications" + maxEventDt="5e5" + target="/Solvers/coupledFlowAndWells"> + - + name="timeHistoryCollection1" + timeFrequency="1e6" + target="/Tasks/wellRateCollection1"> + - + name="timeHistoryCollection2" + timeFrequency="1e6" + target="/Tasks/wellRateCollection2"> + - + name="timeHistoryCollection3" + timeFrequency="1e6" + target="/Tasks/wellRateCollection3"> + - + name="timeHistoryCollection4" + timeFrequency="1e6" + target="/Tasks/wellRateCollection4"> + - + name="restarts" + timeFrequency="7.5e6" + targetExactTimestep="0" + target="/Outputs/restartOutput"> + - - - + name="fluidTPFA"> + - - - - + name="reservoir" + cellBlocks="{*}" + materialList="{fluid, rock, relperm}"> + - + name="wellRegion1" + materialList="{fluid}"> + - - - + name="wellRegion2" + materialList="{fluid}"> + - + name="wellRegion3" + materialList="{fluid}"> + - + name="wellRegion4" + materialList="{fluid}"> + - + name="wellRegion5" + materialList="{fluid}"> + - + name="wellRegion6" + materialList="{fluid}"> + - + name="wellRegion7" + materialList="{fluid}"> + - + name="wellRegion8" + materialList="{fluid}"> + - + name="wellRegion9" + materialList="{fluid}"> + - + name="wellRegion10" + materialList="{fluid}"> + - + name="wellRegion11" + materialList="{fluid}"> + + name="wellRegion12" + materialList="{fluid}"> + - - - + name="fluid" + phaseNames="{oil, water}" + surfaceDensities="{848.9, 1025.2}" + componentMolarWeight="{114e-3, 18e-3}" + tableFiles="{pvdo.txt, pvtw.txt}"> + - + name="relperm" + phaseNames="{oil, water}" + phaseMinVolumeFraction="{0.1, 0.2}" + phaseRelPermExponent="{4.0, 3.0}" + phaseRelPermMaxValue="{0.8, 0.75}"> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + - + name="nullSolid"> + - + name="rockPorosity" + defaultReferencePorosity="0.2" + referencePressure="0.0" + compressibility="1.0e-13"> + + name="rockPerm" + permeabilityComponents="{1.0e-12, 1.0e-12, 1.0e-12}"> + - - - - + name="initialPressure" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/reservoir/hexahedra" + fieldName="pressure" + scale="4e7"> + - + name="initialComposition_oil" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/reservoir/hexahedra" + fieldName="globalCompFraction" + component="0" + scale="0.9"> + + name="initialComposition_water" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/reservoir/hexahedra" + fieldName="globalCompFraction" + component="1" + scale="0.1"> + - - - - + name="vtkOutput"> + - + name="timeHistoryOutput1" + sources="{/Tasks/wellRateCollection1}" + filename="wellRateHistory1"> + - + name="timeHistoryOutput2" + sources="{/Tasks/wellRateCollection2}" + filename="wellRateHistory2"> + - + name="timeHistoryOutput3" + sources="{/Tasks/wellRateCollection3}" + filename="wellRateHistory3"> + - + name="timeHistoryOutput4" + sources="{/Tasks/wellRateCollection4}" + filename="wellRateHistory4"> + - + name="restartOutput"> + - - - - + name="wellRateCollection1" + objectPath="ElementRegions/wellRegion1/wellRegion1UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"> + - + name="wellRateCollection2" + objectPath="ElementRegions/wellRegion2/wellRegion2UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"> + - + name="wellRateCollection3" + objectPath="ElementRegions/wellRegion3/wellRegion3UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"> + + name="wellRateCollection4" + objectPath="ElementRegions/wellRegion4/wellRegion4UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"> + - - - + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d.xml index 7ebac080cbc..1df2ffc30de 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d.xml @@ -1,304 +1,313 @@ - - - + name="reservoirSystem" + wellSolverName="compositionalMultiphaseWell" + flowSolverName="compositionalMultiphaseFlow" + logLevel="1" + initialDt="86400" + targetRegions="{region, wellRegion1, wellRegion2}"> - + maxTimeStepCuts="5" + newtonTol="1e-8" + newtonMaxIter="20"> + + + - - + name="compositionalMultiphaseFlow" + logLevel="1" + discretization="fluidTPFA" + targetRelativePressureChangeInTimeStep="1" + targetPhaseVolFractionChangeInTimeStep="1" + targetRegions="{region}" + temperature="297.15" + useMass="1"> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{wellRegion1, wellRegion2}" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1" + useMass="1" + writeCSV="1"> + name="wellControls1" + type="producer"> + + + + + + name="wellControls2" + type="injector"> + + + + + - - - + name="mesh" + elementTypes="{C3D8}" + xCoords="{0, 200}" + yCoords="{0, 200}" + zCoords="{0, 10}" + nx="{4}" + ny="{4}" + nz="{2}" + cellBlockNames="{cb}"> + name="wellProducer" + wellRegionName="wellRegion1" + wellControlsName="wellControls1" + polylineNodeCoords="{{5.0, 5.0, 2.0}, {5.0, 5.0, 0.0}}" + polylineSegmentConn="{{0, 1}}" + radius="0.1" + numElementsPerSegment="1"> + name="producerPerf1" + distanceFromHead="1.00"> + + name="wellInjector" + wellRegionName="wellRegion2" + wellControlsName="wellControls2" + polylineNodeCoords="{{195.0, 195.0, 2.0}, {195.0, 195.0, 0.0}}" + polylineSegmentConn="{{0, 1}}" + radius="0.1" + numElementsPerSegment="1"> + name="injectorPerf1" + distanceFromHead="1.00"> + - - - - + name="outputs" + timeFrequency="3153600" + targetExactTimestep="1" + target="/Outputs/vtkOutput"> + - + name="timeHistoryOutput" + timeFrequency="3153600" + targetExactTimestep="1" + target="/Outputs/timeHistoryOutput"> + - + name="restarts" + timeFrequency="1576800" + targetExactTimestep="1" + target="/Outputs/restartOutput"> + - + name="solverApplications" + maxEventDt="315360" + target="/Solvers/reservoirSystem"> + - + name="statistics" + timeFrequency="3153600" + target="/Tasks/compositionalMultiphaseFlowStatistics"> + - + name="timeHistoryCollection" + timeFrequency="315360" + targetExactTimestep="1" + target="/Tasks/wellRateCollection"> + - + name="fluidTPFA"> + - + name="region" + cellBlocks="{*}" + materialList="{fluid, rock, relperm, cappres}"> + + name="wellRegion1" + materialList="{fluid}"> + + name="wellRegion2" + materialList="{fluid}"> + - - + name="fluid" + phaseNames="{oil, gas, water}" + surfaceDensities="{800.907131537, 0.856234902739, 1020.3440}" + componentMolarWeight="{120e-3, 25e-3, 18e-3}" + tableFiles="{pvto_bo.txt, pvtg_norv_bo.txt, pvtw_bo.txt}"> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + - + name="nullSolid"> + - + name="rockPorosity" + defaultReferencePorosity="0.2" + referencePressure="4.1369e7" + compressibility="1.0e-9"> + - + name="relperm" + phaseNames="{oil, gas, water}" + wettingIntermediateRelPermTableNames="{waterRelPermTable, oilRelPermTableForOW}" + nonWettingIntermediateRelPermTableNames="{gasRelPermTable, oilRelPermTableForOG}"> + - + name="cappres" + phaseNames="{oil, gas, water}" + wettingIntermediateCapPressureTableName="waterCapPresTable" + nonWettingIntermediateCapPressureTableName="gasCapPresTable"> + - + name="rockPerm" + permeabilityComponents="{1.0e-14, 1.0e-14, 1.0e-14}"> + - - + name="initialPressure" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="pressure" + scale="1.5e+7"> + + name="initialComposition_oil" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="0" + scale="0.79999"> + + name="initialComposition_gas" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="1" + scale="0.2"> + + name="initialComposition_water" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="2" + scale="0.00001"> + - - + name="waterRelPermTable" + coordinates="{0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, + 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00}" + values="{0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, 0.2500, 0.3025, + 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000}"> + + name="oilRelPermTableForOW" + coordinates="{0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, + 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00}" + values="{0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, 0.2500, 0.3025, + 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000}"> + + name="gasRelPermTable" + coordinates="{0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, + 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00}" + values="{0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, 0.2500, 0.3025, + 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000}"> + - + name="oilRelPermTableForOG" + coordinates="{0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, + 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00}" + values="{0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, 0.2500, 0.3025, + 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000}"> + + name="waterCapPresTable" + coordinates="{0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, + 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00}" + values="{10000, 9025, 8100, 7225, 6400, 5625, 4900, 4225, 3600, 3025, 2500, 2025, 1600, 1225, 900, + 625, 400, 225, 100, 25, 0}"> + - + name="gasCapPresTable" + coordinates="{0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, + 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00}" + values="{0, 50, 200, 450, 800, 1250, 1800, 2450, 3200, 4050, 5000, 6050, 7200, 8450, 9800, 11250, + 12800, 14450, 16200, 18050, 20000}"> + - - + name="compositionalMultiphaseFlowStatistics" + flowSolverName="compositionalMultiphaseFlow" + logLevel="1" + computeCFLNumbers="1" + computeRegionStatistics="1"> + + name="wellRateCollection" + objectPath="ElementRegions/wellRegion1/wellRegion1UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"> + - - + name="vtkOutput"> + - + name="timeHistoryOutput" + sources="{/Tasks/wellRateCollection}" + filename="wellRateHistory"> + + name="restartOutput"> + - - + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml index ce669961545..1b3b56c03cd 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml @@ -1,304 +1,314 @@ - - - + name="reservoirSystem" + wellSolverName="compositionalMultiphaseWell" + flowSolverName="compositionalMultiphaseFlow" + logLevel="1" + initialDt="86400" + targetRegions="{region, wellRegion1, wellRegion2}"> - + maxTimeStepCuts="5" + newtonTol="1e-8" + newtonMaxIter="20"> + + + - - + name="compositionalMultiphaseFlow" + logLevel="1" + discretization="fluidTPFA" + targetRelativePressureChangeInTimeStep="1" + targetPhaseVolFractionChangeInTimeStep="1" + targetRegions="{region}" + temperature="297.15" + useMass="1"> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{wellRegion1, wellRegion2}" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1" + useMass="1" + writeCSV="1"> + name="wellControls1" + type="producer"> + + + + + + name="wellControls2" + type="injector"> + + + + + - - - - - - - - + name="mesh" + elementTypes="{C3D8}" + xCoords="{0, 200}" + yCoords="{0, 200}" + zCoords="{0, 10}" + nx="{4}" + ny="{4}" + nz="{2}" + cellBlockNames="{cb}"> + + + + + + + + - - - - + name="outputs" + timeFrequency="3153600" + targetExactTimestep="1" + target="/Outputs/vtkOutput"> + - + name="timeHistoryOutput" + timeFrequency="3153600" + targetExactTimestep="1" + target="/Outputs/timeHistoryOutput"> + - + name="restarts" + timeFrequency="1576800" + targetExactTimestep="1" + target="/Outputs/restartOutput"> + - + name="solverApplications" + maxEventDt="315360" + target="/Solvers/reservoirSystem"> + - + name="statistics" + timeFrequency="3153600" + target="/Tasks/compositionalMultiphaseFlowStatistics"> + - + name="timeHistoryCollection" + timeFrequency="315360" + targetExactTimestep="1" + target="/Tasks/wellRateCollection"> + - + name="fluidTPFA"> + - + name="region" + cellBlocks="{*}" + materialList="{fluid, rock, relperm, cappres}"> + + name="wellRegion1" + materialList="{fluid}"> + + name="wellRegion2" + materialList="{fluid}"> + - - + name="fluid" + phaseNames="{oil, gas, water}" + surfaceDensities="{800.907131537, 0.856234902739, 1020.3440}" + componentMolarWeight="{120e-3, 25e-3, 18e-3}" + tableFiles="{pvto_bo.txt, pvtg_norv_bo.txt, pvtw_bo.txt}"> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + - + name="nullSolid"> + - + name="rockPorosity" + defaultReferencePorosity="0.2" + referencePressure="4.1369e7" + compressibility="1.0e-9"> + - + name="relperm" + phaseNames="{oil, gas, water}" + wettingIntermediateRelPermTableNames="{waterRelPermTable, oilRelPermTableForOW}" + nonWettingIntermediateRelPermTableNames="{gasRelPermTable, oilRelPermTableForOG}" + threePhaseInterpolator="STONEII"> + - + name="cappres" + phaseNames="{oil, gas, water}" + wettingIntermediateCapPressureTableName="waterCapPresTable" + nonWettingIntermediateCapPressureTableName="gasCapPresTable"> + - + name="rockPerm" + permeabilityComponents="{1.0e-14, 1.0e-14, 1.0e-14}"> + - - + name="initialPressure" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="pressure" + scale="1.5e+7"> + + name="initialComposition_oil" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="0" + scale="0.79999"> + + name="initialComposition_gas" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="1" + scale="0.2"> + + name="initialComposition_water" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="2" + scale="0.00001"> + - - + name="waterRelPermTable" + coordinates="{0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, + 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00}" + values="{0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, 0.2500, 0.3025, + 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000}"> + + name="oilRelPermTableForOW" + coordinates="{0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, + 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00}" + values="{0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, 0.2500, 0.3025, + 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000}"> + + name="gasRelPermTable" + coordinates="{0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, + 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00}" + values="{0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, 0.2500, 0.3025, + 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000}"> + - + name="oilRelPermTableForOG" + coordinates="{0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, + 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00}" + values="{0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, 0.2500, 0.3025, + 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000}"> + + name="waterCapPresTable" + coordinates="{0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, + 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00}" + values="{10000, 9025, 8100, 7225, 6400, 5625, 4900, 4225, 3600, 3025, 2500, 2025, 1600, 1225, 900, + 625, 400, 225, 100, 25, 0}"> + - + name="gasCapPresTable" + coordinates="{0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, + 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00}" + values="{0, 50, 200, 450, 800, 1250, 1800, 2450, 3200, 4050, 5000, 6050, 7200, 8450, 9800, 11250, + 12800, 14450, 16200, 18050, 20000}"> + - - + name="compositionalMultiphaseFlowStatistics" + flowSolverName="compositionalMultiphaseFlow" + logLevel="1" + computeCFLNumbers="1" + computeRegionStatistics="1"> + + name="wellRateCollection" + objectPath="ElementRegions/wellRegion1/wellRegion1UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"> + - - + name="vtkOutput"> + - + name="timeHistoryOutput" + sources="{/Tasks/wellRateCollection}" + filename="wellRateHistory"> + + name="restartOutput"> + - - + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml index 323b9a144c6..e2aa359a44e 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml @@ -1,258 +1,265 @@ - - - + name="reservoirSystem" + wellSolverName="compositionalMultiphaseWell" + flowSolverName="compositionalMultiphaseFlow" + logLevel="1" + initialDt="86400" + targetRegions="{region, wellRegion1, wellRegion2}"> - + maxTimeStepCuts="5" + newtonTol="1e-8" + newtonMaxIter="20"> + + + - + name="compositionalMultiphaseFlow" + logLevel="1" + discretization="fluidHM" + targetRelativePressureChangeInTimeStep="1" + targetPhaseVolFractionChangeInTimeStep="1" + targetRegions="{region}" + temperature="297.15" + useMass="1"> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{wellRegion1, wellRegion2}" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1" + useMass="1" + writeCSV="1"> + name="wellControls1" + type="producer"> + + + + + + name="wellControls2" + type="injector"> + + + + + - - - + name="mesh" + elementTypes="{C3D8}" + xCoords="{0, 200}" + yCoords="{0, 200}" + zCoords="{0, 10}" + nx="{4}" + ny="{4}" + nz="{2}" + cellBlockNames="{cb}"> + name="wellProducer" + wellRegionName="wellRegion1" + wellControlsName="wellControls1" + polylineNodeCoords="{{5.0, 5.0, 2.0}, {5.0, 5.0, 0.0}}" + polylineSegmentConn="{{0, 1}}" + radius="0.1" + numElementsPerSegment="1"> + name="producerPerf1" + distanceFromHead="1.00"> + + name="wellInjector" + wellRegionName="wellRegion2" + wellControlsName="wellControls2" + polylineNodeCoords="{{195.0, 195.0, 2.0}, {195.0, 195.0, 0.0}}" + polylineSegmentConn="{{0, 1}}" + radius="0.1" + numElementsPerSegment="1"> + name="injectorPerf1" + distanceFromHead="1.00"> + - - - + - + name="outputs" + timeFrequency="3153600" + targetExactTimestep="1" + target="/Outputs/vtkOutput"> + - - - + name="timeHistoryOutput" + timeFrequency="3153600" + targetExactTimestep="1" + target="/Outputs/timeHistoryOutput"> + - + name="restarts" + timeFrequency="1576800" + targetExactTimestep="1" + target="/Outputs/restartOutput"> + - + name="solverApplications" + maxEventDt="315360" + target="/Solvers/reservoirSystem"> + - + name="statistics" + timeFrequency="3153600" + target="/Tasks/compositionalMultiphaseFlowStatistics"> + + + - + name="fluidHM" + innerProductType="TPFA"> + - + name="region" + cellBlocks="{*}" + materialList="{fluid, rock, relperm}"> + + name="wellRegion1" + materialList="{fluid}"> + + name="wellRegion2" + materialList="{fluid}"> + - - + name="fluid" + phaseNames="{oil, gas, water}" + surfaceDensities="{800.907131537, 0.856234902739, 1020.3440}" + componentMolarWeight="{120e-3, 25e-3, 18e-3}" + tableFiles="{pvto_bo.txt, pvtg_norv_bo.txt, pvtw_bo.txt}"> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + - + name="nullSolid"> + - + name="rockPorosity" + defaultReferencePorosity="0.2" + referencePressure="4.1369e7" + compressibility="1.0e-9"> + - + name="relperm" + phaseNames="{oil, gas, water}" + phaseMinVolumeFraction="{0.0, 0.0, 0.0}" + phaseRelPermExponent="{2.0, 2.0, 2.0}" + phaseRelPermMaxValue="{1.0, 1.0, 1.0}"> + - + name="rockPerm" + permeabilityComponents="{1.0e-14, 1.0e-14, 1.0e-14}"> + - - + name="initialPressure" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="pressure" + scale="1.5e+7"> + + name="initialComposition_oil" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="0" + scale="0.89999"> + + name="initialComposition_gas" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="1" + scale="0.1"> + + name="initialComposition_water" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="2" + scale="0.00001"> + - - + - + name="compositionalMultiphaseFlowStatistics" + flowSolverName="compositionalMultiphaseFlow" + logLevel="1" + computeCFLNumbers="0" + computeRegionStatistics="1"> + + name="wellRateCollection" + objectPath="ElementRegions/wellRegion1/wellRegion1UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"> + - - + name="vtkOutput"> + - + name="timeHistoryOutput" + sources="{/Tasks/wellRateCollection}" + filename="wellRateHistory"> + - + name="restartOutput"> + - - + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml index ea41c8adf9c..04ae87437ad 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml @@ -1,260 +1,267 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_1d.xml b/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_1d.xml index bea2c48815d..a734fa1ca50 100644 --- a/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_1d.xml +++ b/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_1d.xml @@ -1,232 +1,234 @@ - - + name="reservoirSystem" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{Region1, wellRegion1, wellRegion2}"> + newtonTol="1.0e-8" + lineSearchAction="None" + newtonMaxIter="40"> + + directParallel="0"> + - - + name="compositionalMultiphaseFlow" + logLevel="1" + discretization="fluidTPFA" + targetRegions="{Region1}" + temperature="297.15"> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{wellRegion1, wellRegion2}" + writeCSV="1"> + name="wellControls1" + type="producer"> + + + + + + name="wellControls2" + type="injector"> + + + + + - - + name="mesh1" + elementTypes="{C3D8}" + xCoords="{0, 5}" + yCoords="{0, 1}" + zCoords="{0, 1}" + nx="{5}" + ny="{1}" + nz="{1}" + cellBlockNames="{cb1}"> + name="well_producer1" + wellRegionName="wellRegion1" + wellControlsName="wellControls1" + polylineNodeCoords="{{4.5, 0, 2}, {4.5, 0, 0.5}}" + polylineSegmentConn="{{0, 1}}" + radius="0.1" + numElementsPerSegment="2"> + name="producer1_perf1" + distanceFromHead="1.45"> + - + name="well_injector1" + wellRegionName="wellRegion2" + wellControlsName="wellControls2" + polylineNodeCoords="{{0.5, 0, 2}, {0.5, 0, 0.5}}" + polylineSegmentConn="{{0, 1}}" + radius="0.1" + numElementsPerSegment="3"> + name="injector1_perf1" + distanceFromHead="1.45"> + - + maxTime="2.5e4"> - + name="solverApplications" + forceDt="2.5e3" + target="/Solvers/reservoirSystem"> + - + name="outputs" + timeFrequency="2.5e3" + target="/Outputs/vtkOutput"> + + name="restarts" + timeFrequency="1.25e4" + targetExactTimestep="0" + target="/Outputs/restartOutput"> + - + name="fluidTPFA"> + - - + name="Region1" + cellBlocks="{*}" + materialList="{fluid1, rock, relperm}"> + - + name="wellRegion1" + materialList="{fluid1}"> + + name="wellRegion2" + materialList="{fluid1}"> + - - + name="fluid1" + phaseNames="{oil, gas}" + equationsOfState="{PR, PR}" + componentNames="{N2, C10, C20, H2O}" + componentCriticalPressure="{34e5, 25.3e5, 14.6e5, 220.5e5}" + componentCriticalTemperature="{126.2, 622.0, 782.0, 647.0}" + componentAcentricFactor="{0.04, 0.443, 0.816, 0.344}" + componentMolarWeight="{28e-3, 134e-3, 275e-3, 18e-3}" + componentVolumeShift="{0, 0, 0, 0}" + componentBinaryCoeff="{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}"> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + - + name="nullSolid"> + - + name="rockPorosity" + defaultReferencePorosity="0.05" + referencePressure="0.0" + compressibility="1.0e-9"> + - + name="relperm" + phaseNames="{oil, gas}" + phaseMinVolumeFraction="{0.1, 0.15}" + phaseRelPermExponent="{2.0, 2.0}" + phaseRelPermMaxValue="{0.8, 0.9}"> + + name="rockPerm" + permeabilityComponents="{2.0e-16, 2.0e-16, 2.0e-16}"> + - - - - + name="initialPressure" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Region1/cb1" + fieldName="pressure" + scale="5e6"> + - + name="initialComposition_N2" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="0" + scale="0.099"> + - + name="initialComposition_C10" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="1" + scale="0.3"> + - + name="initialComposition_C20" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="2" + scale="0.6"> + + name="initialComposition_H20" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="3" + scale="0.001"> + - - + name="vtkOutput"> + + name="restartOutput"> + - + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_2d.xml b/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_2d.xml index 81e2212e304..1deb55d537f 100644 --- a/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_2d.xml +++ b/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_2d.xml @@ -1,280 +1,285 @@ - - + name="reservoirSystem" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{Region1, wellRegion1, wellRegion2, wellRegion3}"> + newtonTol="1.0e-8" + lineSearchAction="None" + newtonMaxIter="40"> + + directParallel="0"> + - - - + name="compositionalMultiphaseFlow" + logLevel="1" + discretization="fluidTPFA" + targetRegions="{Region1}" + temperature="297.15"> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{wellRegion1, wellRegion2, wellRegion3}" + writeCSV="1"> + name="wellControls1" + type="producer"> + + + + + + name="wellControls2" + type="producer"> + + + + + + name="wellControls3" + type="injector"> + + + + + - - - - + name="mesh1" + elementTypes="{C3D8}" + xCoords="{0, 15}" + yCoords="{0, 15}" + zCoords="{0, 1}" + nx="{20}" + ny="{20}" + nz="{1}" + cellBlockNames="{cb1}"> + name="well_producer1" + wellRegionName="wellRegion1" + wellControlsName="wellControls1" + polylineNodeCoords="{{0.5, 0.5, 0.5}, {7.5, 0.5, 0.35}, {14.5, 0.5, 0.2}}" + polylineSegmentConn="{{0, 1}, {1, 2}}" + radius="0.1" + numElementsPerSegment="20"> + name="producer1_perf1" + distanceFromHead="14"> + + name="producer1_perf2" + distanceFromHead="11"> + + name="producer1_perf3" + distanceFromHead="8"> + - + name="well_producer2" + wellRegionName="wellRegion2" + wellControlsName="wellControls2" + polylineNodeCoords="{{14.5, 14.5, 0.5}, {7.5, 14.5, 0.35}, {0.5, 14.5, 0.2}}" + polylineSegmentConn="{{0, 1}, {1, 2}}" + radius="0.1" + numElementsPerSegment="17"> + name="producer2_perf1" + distanceFromHead="14."> + + name="producer2_perf2" + distanceFromHead="10"> + + name="producer2_perf3" + distanceFromHead="6"> + - + name="well_injector1" + wellRegionName="wellRegion3" + wellControlsName="wellControls3" + polylineNodeCoords="{{0.5, 0.5, 0.5}, {14.5, 14.5, 0.2}}" + polylineSegmentConn="{{0, 1}}" + radius="0.1" + numElementsPerSegment="30"> + name="injector1_perf1" + distanceFromHead="19.5"> + + name="injector1_perf2" + distanceFromHead="10.45"> + - + maxTime="7e3"> - + name="solverApplications" + forceDt="1e3" + target="/Solvers/reservoirSystem"> + - + name="outputs" + timeFrequency="1e3" + target="/Outputs/siloOutput"> + + name="restarts" + timeFrequency="3e3" + targetExactTimestep="0" + target="/Outputs/restartOutput"> + - + name="fluidTPFA"> + - - + name="Region1" + cellBlocks="{*}" + materialList="{fluid1, rock, relperm}"> + - + name="wellRegion1" + materialList="{fluid1}"> + - + name="wellRegion2" + materialList="{fluid1}"> + + name="wellRegion3" + materialList="{fluid1}"> + - - + name="fluid1" + phaseNames="{oil, gas}" + equationsOfState="{PR, PR}" + componentNames="{N2, C10, C20, H2O}" + componentCriticalPressure="{34e5, 25.3e5, 14.6e5, 220.5e5}" + componentCriticalTemperature="{126.2, 622.0, 782.0, 647.0}" + componentAcentricFactor="{0.04, 0.443, 0.816, 0.344}" + componentMolarWeight="{28e-3, 134e-3, 275e-3, 18e-3}" + componentVolumeShift="{0, 0, 0, 0}" + componentBinaryCoeff="{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}"> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + - + name="nullSolid"> + - + name="rockPorosity" + defaultReferencePorosity="0.05" + referencePressure="0.0" + compressibility="1.0e-9"> + - + name="relperm" + phaseNames="{oil, gas}" + phaseMinVolumeFraction="{0.1, 0.15}" + phaseRelPermExponent="{2.0, 2.0}" + phaseRelPermMaxValue="{0.8, 0.9}"> + + name="rockPerm" + permeabilityComponents="{2.0e-16, 2.0e-16, 2.0e-16}"> + - - - - + name="initialPressure" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Region1/cb1" + fieldName="pressure" + scale="5e6"> + - + name="initialComposition_N2" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="0" + scale="0.099"> + - + name="initialComposition_C10" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="1" + scale="0.3"> + - + name="initialComposition_C20" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="2" + scale="0.6"> + + name="initialComposition_H20" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="3" + scale="0.001"> + - - + name="siloOutput"> + + name="restartOutput"> + - + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/dead_oil_wells_2d.xml b/inputFiles/compositionalMultiphaseWell/dead_oil_wells_2d.xml index 4e97569f8f9..ba23381034b 100644 --- a/inputFiles/compositionalMultiphaseWell/dead_oil_wells_2d.xml +++ b/inputFiles/compositionalMultiphaseWell/dead_oil_wells_2d.xml @@ -1,301 +1,311 @@ - - + name="reservoirSystem" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{Region1, wellRegion1, wellRegion2, wellRegion3}"> + newtonTol="1e-8" + newtonMaxIter="40"> + + directParallel="0"> + - - + name="compositionalMultiphaseFlow" + logLevel="1" + targetRelativePressureChangeInTimeStep="1" + targetPhaseVolFractionChangeInTimeStep="1" + discretization="fluidTPFA" + targetRegions="{Region1}" + temperature="297.15"> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{wellRegion1, wellRegion2, wellRegion3}" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1" + writeCSV="1"> + name="wellControls1" + type="producer" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="297.15"> + + + + + + name="wellControls2" + type="producer" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="297.15"> + + + + + + name="wellControls3" + type="injector" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="297.15"> + + + + + - - + name="mesh1" + elementTypes="{C3D8}" + xCoords="{0, 15}" + yCoords="{0, 15}" + zCoords="{0, 1}" + nx="{20}" + ny="{20}" + nz="{1}" + cellBlockNames="{cb1}"> + name="well_producer1" + wellRegionName="wellRegion1" + wellControlsName="wellControls1" + polylineNodeCoords="{{0.5, 0.5, 0.5}, {7.5, 0.5, 0.35}, {14.5, 0.5, 0.2}}" + polylineSegmentConn="{{0, 1}, {1, 2}}" + radius="0.1" + numElementsPerSegment="20"> + name="producer1_perf1" + distanceFromHead="14"> + + name="producer1_perf2" + distanceFromHead="11"> + + name="producer1_perf3" + distanceFromHead="8"> + - + name="well_producer2" + wellRegionName="wellRegion2" + wellControlsName="wellControls2" + polylineNodeCoords="{{14.5, 14.5, 0.5}, {7.5, 14.5, 0.35}, {0.5, 14.5, 0.2}}" + polylineSegmentConn="{{0, 1}, {1, 2}}" + radius="0.1" + numElementsPerSegment="17"> + name="producer2_perf1" + distanceFromHead="14."> + + name="producer2_perf2" + distanceFromHead="10"> + + name="producer2_perf3" + distanceFromHead="6"> + - + name="well_injector1" + wellRegionName="wellRegion3" + wellControlsName="wellControls3" + polylineNodeCoords="{{0.5, 0.5, 0.5}, {14.5, 14.5, 0.2}}" + polylineSegmentConn="{{0, 1}}" + radius="0.1" + numElementsPerSegment="30"> + name="injector1_perf1" + distanceFromHead="19.5"> + + name="injector1_perf2" + distanceFromHead="10.45"> + - + maxTime="5e5"> - + name="solverApplications" + forceDt="5e3" + target="/Solvers/reservoirSystem"> + - + name="outputs" + timeFrequency="5e4" + target="/Outputs/vtkOutput"> + + name="restarts" + timeFrequency="2.5e5" + targetExactTimestep="0" + target="/Outputs/restartOutput"> + - + name="fluidTPFA"> + - - + name="Region1" + cellBlocks="{*}" + materialList="{fluid1, rock, relperm}"> + - + name="wellRegion1" + materialList="{fluid1}"> + - + name="wellRegion2" + materialList="{fluid1}"> + + name="wellRegion3" + materialList="{fluid1}"> + - - + name="fluid1" + phaseNames="{oil, gas, water}" + surfaceDensities="{800.0, 0.9907, 1022.0}" + componentMolarWeight="{114e-3, 16e-3, 18e-3}" + tableFiles="{pvdo.txt, pvdg.txt, pvtw.txt}"> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + - + name="nullSolid"> + - + name="rockPorosity" + defaultReferencePorosity="0.05" + referencePressure="0.0" + compressibility="1.0e-9"> + - + name="relperm" + phaseNames="{oil, gas, water}" + wettingIntermediateRelPermTableNames="{waterRelPermTable, oilRelPermTableForOW}" + nonWettingIntermediateRelPermTableNames="{gasRelPermTable, oilRelPermTableForOG}"> + + name="rockPerm" + permeabilityComponents="{2.0e-16, 2.0e-16, 2.0e-16}"> + - - - - + name="initialPressure" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Region1/cb1" + fieldName="pressure" + scale="5e6"> + - + name="initialComposition_oil" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="0" + scale="0.6"> + - + name="initialComposition_gas" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="1" + scale="0.399"> + + name="initialComposition_water" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="2" + scale="0.001"> + - - - + name="BHPTable" + inputVarNames="{time}" + coordinates="{0, 10e10}" + values="{4e6, 4e6}" + interpolation="lower"> + - + name="waterRelPermTable" + coordinateFiles="{satw.txt}" + voxelFile="krw.txt"> + - + name="oilRelPermTableForOW" + coordinateFiles="{sato.txt}" + voxelFile="krow.txt"> + - + name="gasRelPermTable" + coordinateFiles="{satg.txt}" + voxelFile="krg.txt"> + + name="oilRelPermTableForOG" + coordinateFiles="{sato.txt}" + voxelFile="krog.txt"> + - - + name="vtkOutput"> + + name="restartOutput"> + - + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/dead_oil_wells_hybrid_2d.xml b/inputFiles/compositionalMultiphaseWell/dead_oil_wells_hybrid_2d.xml index 8434ee6c709..f88b830bb37 100644 --- a/inputFiles/compositionalMultiphaseWell/dead_oil_wells_hybrid_2d.xml +++ b/inputFiles/compositionalMultiphaseWell/dead_oil_wells_hybrid_2d.xml @@ -1,279 +1,291 @@ - - + name="reservoirSystem" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{Region1, wellRegion1, wellRegion2, wellRegion3}"> + newtonMaxIter="40"> + + directParallel="0"> + - - + name="compositionalMultiphaseFlow" + logLevel="1" + targetRelativePressureChangeInTimeStep="1" + targetPhaseVolFractionChangeInTimeStep="1" + discretization="fluidHM" + targetRegions="{Region1}" + temperature="297.15"> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{wellRegion1, wellRegion2, wellRegion3}" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1" + writeCSV="1"> + name="wellControls1" + type="producer" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="297.15"> + + + + + + name="wellControls2" + type="producer" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="297.15"> + + + + + + name="wellControls3" + type="injector" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="297.15"> + + + + + - - + name="mesh1" + elementTypes="{C3D8}" + xCoords="{0, 15}" + yCoords="{0, 15}" + zCoords="{0, 1}" + nx="{20}" + ny="{20}" + nz="{1}" + cellBlockNames="{cb1}"> + name="well_producer1" + wellRegionName="wellRegion1" + wellControlsName="wellControls1" + polylineNodeCoords="{{0.5, 0.5, 0.5}, {7.5, 0.5, 0.35}, {14.5, 0.5, 0.2}}" + polylineSegmentConn="{{0, 1}, {1, 2}}" + radius="0.1" + numElementsPerSegment="20"> + name="producer1_perf1" + distanceFromHead="14"> + + name="producer1_perf2" + distanceFromHead="11"> + + name="producer1_perf3" + distanceFromHead="8"> + - + name="well_producer2" + wellRegionName="wellRegion2" + wellControlsName="wellControls2" + polylineNodeCoords="{{14.5, 14.5, 0.5}, {7.5, 14.5, 0.35}, {0.5, 14.5, 0.2}}" + polylineSegmentConn="{{0, 1}, {1, 2}}" + radius="0.1" + numElementsPerSegment="17"> + name="producer2_perf1" + distanceFromHead="14."> + + name="producer2_perf2" + distanceFromHead="10"> + + name="producer2_perf3" + distanceFromHead="6"> + - + name="well_injector1" + wellRegionName="wellRegion3" + wellControlsName="wellControls3" + polylineNodeCoords="{{0.5, 0.5, 0.5}, {14.5, 14.5, 0.2}}" + polylineSegmentConn="{{0, 1}}" + radius="0.1" + numElementsPerSegment="30"> + name="injector1_perf1" + distanceFromHead="19.5"> + + name="injector1_perf2" + distanceFromHead="10.45"> + - + maxTime="5e5"> - + name="solverApplications" + forceDt="5e3" + target="/Solvers/reservoirSystem"> + - + name="outputs" + timeFrequency="5e4" + target="/Outputs/siloOutput"> + + name="restarts" + timeFrequency="2.5e5" + targetExactTimestep="0" + target="/Outputs/restartOutput"> + - + name="fluidHM" + innerProductType="beiraoDaVeigaLipnikovManzini"> + - - + name="Region1" + cellBlocks="{*}" + materialList="{fluid, rock, relperm}"> + - + name="wellRegion1" + materialList="{fluid}"> + - + name="wellRegion2" + materialList="{fluid}"> + + name="wellRegion3" + materialList="{fluid}"> + - - + name="fluid" + phaseNames="{oil, gas, water}" + surfaceDensities="{800.0, 0.9907, 1022.0}" + componentMolarWeight="{114e-3, 16e-3, 18e-3}" + tableFiles="{pvdo.txt, pvdg.txt, pvtw.txt}"> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + - + name="nullSolid"> + - + name="rockPorosity" + defaultReferencePorosity="0.05" + referencePressure="0.0" + compressibility="1.0e-9"> + - + name="relperm" + phaseNames="{oil, gas, water}" + phaseMinVolumeFraction="{0.05, 0.05, 0.05}" + phaseRelPermExponent="{2.0, 2.0, 1.5}" + phaseRelPermMaxValue="{0.8, 0.9, 0.9}"> + + name="rockPerm" + permeabilityComponents="{2.0e-16, 2.0e-16, 2.0e-16}"> + - - - + name="initialPressure" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Region1/cb1" + fieldName="pressure" + scale="5e6"> + - - + name="initialFacePressure" + initialCondition="1" + setNames="{all}" + objectPath="faceManager" + fieldName="facePressure" + scale="5e6"> + - + name="initialComposition_oil" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="0" + scale="0.6"> + - + name="initialComposition_gas" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="1" + scale="0.399"> + + name="initialComposition_water" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="2" + scale="0.001"> + - - + name="siloOutput"> + + name="restartOutput"> + - + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/isothm_mass_inj_table.xml b/inputFiles/compositionalMultiphaseWell/isothm_mass_inj_table.xml index 14076fab917..44fa791c2e9 100644 --- a/inputFiles/compositionalMultiphaseWell/isothm_mass_inj_table.xml +++ b/inputFiles/compositionalMultiphaseWell/isothm_mass_inj_table.xml @@ -1,229 +1,232 @@ - - + name="coupledFlowAndWells" + flowSolverName="compflow" + wellSolverName="compositionalMultiphaseWell" + logLevel="4" + initialDt="1e2" + targetRegions="{region, injwell}"> + logLevel="4" + newtonTol="1.0e-3" + timeStepDecreaseIterLimit="0.41" + newtonMaxIter="40" + lineSearchAction="None"> + + logLevel="4" + solverType="fgmres" + krylovTol="1e-4"> + - + name="compflow" + logLevel="4" + discretization="fluidTPFA" + temperature="368.15" + useMass="1" + initialDt="1e2" + maxCompFractionChange="0.5" + targetRegions="{region}"> - + name="compositionalMultiphaseWell" + targetRegions="{injwell}" + writeCSV="1" + logLevel="1" + useMass="1"> - + name="WC_CO2_INJ" + logLevel="2" + type="injector" + enableCrossflow="0" + useSurfaceConditions="1" + surfacePressure="1.45e7" + surfaceTemperature="300.15" + targetMassRateTableName="totalMassRateTable"> + + + + + + - + name="mesh1" + elementTypes="{C3D8}" + xCoords="{0, 2000}" + yCoords="{0, 2000}" + zCoords="{0, 2000}" + nx="{1}" + ny="{4}" + nz="{1}" + cellBlockNames="{cb}"> + name="inj1" + wellRegionName="injwell" + wellControlsName="WC_CO2_INJ" + logLevel="1" + polylineNodeCoords="{{50.0, 30.0, 51.01}, {50.0, 1450.0, 51.00}}" + polylineSegmentConn="{{0, 1}}" + radius="0.1" + numElementsPerSegment="2"> + name="injector1_perf3" + distanceFromHead="171.93"> + - + name="injector1_perf17" + distanceFromHead="1334.738"> + - - - - + name="sink" + xMin="{89.99, 89.99, -0.01}" + xMax="{101.01, 101.01, 1.01}"> + - + maxTime="2.5e5"> - + name="outputs" + timeFrequency="2.5e4" + target="/Outputs/vtkOutput"> + - + name="solverApplications" + maxEventDt="2.5e4" + target="/Solvers/coupledFlowAndWells"> + + name="restarts" + timeFrequency="2.5e4" + target="/Outputs/sidreRestart"> + - - - + + + + - + name="fluidTPFA"> + - + name="region" + cellBlocks="{cb}" + materialList="{fluid, rock, relperm}"> + + name="injwell" + materialList="{fluid, relperm}"> + - - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + + name="nullSolid"> + + name="rockPorosity" + defaultReferencePorosity="0.2" + referencePressure="0.0" + compressibility="1.0e-9"> + - + name="rockPerm" + permeabilityComponents="{1.0e-13, 1.0e-13, 1.0e-13}"> + - + name="fluid" + logLevel="1" + phaseNames="{gas, water}" + componentNames="{co2, water}" + componentMolarWeight="{44e-3, 18e-3}" + phasePVTParaFiles="{pvtgas.txt, pvtliquid.txt}" + flashModelParaFile="co2flash.txt"> + - + name="relperm" + phaseNames="{gas, water}" + phaseMinVolumeFraction="{0.0, 0.0}" + phaseRelPermExponent="{1.5, 1.5}" + phaseRelPermMaxValue="{0.9, 0.9}"> + - - + name="initialPressure" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="pressure" + scale="9e6"> + + name="initialTemperature" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="temperature" + scale="368.15"> + + name="initialComposition_co2" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="0" + scale="0.005"> + - + name="initialComposition_water" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="1" + scale="0.995"> + - - + name="vtkOutput"> + + name="sidreRestart"> + - + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml b/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml index d39421e36fc..f03b18d24b8 100644 --- a/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml +++ b/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml @@ -1,234 +1,238 @@ - - + name="coupledFlowAndWells" + flowSolverName="compflow" + wellSolverName="compositionalMultiphaseWell" + logLevel="4" + initialDt="1e2" + targetRegions="{region, injwell}"> + logLevel="4" + newtonTol="1.0e-3" + timeStepDecreaseIterLimit="0.41" + newtonMaxIter="40" + lineSearchAction="None"> + + logLevel="4" + solverType="fgmres" + krylovTol="1e-4"> + - + name="compflow" + logLevel="4" + discretization="fluidTPFA" + temperature="368.15" + useMass="1" + initialDt="1e2" + maxCompFractionChange="0.5" + targetRegions="{region}"> - + name="compositionalMultiphaseWell" + targetRegions="{injwell}" + writeCSV="1" + logLevel="1" + useMass="1"> - + name="WC_CO2_INJ" + logLevel="2" + type="injector" + enableCrossflow="0" + useSurfaceConditions="1" + surfacePressure="1.45e7" + surfaceTemperature="300.15"> + + + + + + - + name="mesh1" + elementTypes="{C3D8}" + xCoords="{0, 2000}" + yCoords="{0, 2000}" + zCoords="{0, 2000}" + nx="{1}" + ny="{4}" + nz="{1}" + cellBlockNames="{cb}"> + name="inj1" + wellRegionName="injwell" + wellControlsName="WC_CO2_INJ" + logLevel="1" + polylineNodeCoords="{{50.0, 30.0, 51.01}, {50.0, 1450.0, 51.00}}" + polylineSegmentConn="{{0, 1}}" + radius="0.1" + numElementsPerSegment="2"> + name="injector1_perf3" + distanceFromHead="171.93"> + - + name="injector1_perf17" + distanceFromHead="1334.738"> + - - - - + name="sink" + xMin="{89.99, 89.99, -0.01}" + xMax="{101.01, 101.01, 1.01}"> + - + maxTime="2.5e5"> - + name="outputs" + timeFrequency="2.5e4" + target="/Outputs/vtkOutput"> + - + name="solverApplications" + maxEventDt="2.5e4" + target="/Solvers/coupledFlowAndWells"> + + name="restarts" + timeFrequency="2.5e4" + target="/Outputs/sidreRestart"> + - - - - + + + + + + - + name="fluidTPFA"> + - + name="region" + cellBlocks="{cb}" + materialList="{fluid, rock, relperm}"> + + name="injwell" + materialList="{fluid, relperm}"> + - - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + + name="nullSolid"> + + name="rockPorosity" + defaultReferencePorosity="0.2" + referencePressure="0.0" + compressibility="1.0e-9"> + - + name="rockPerm" + permeabilityComponents="{1.0e-13, 1.0e-13, 1.0e-13}"> + - + name="fluid" + logLevel="1" + phaseNames="{gas, water}" + componentNames="{co2, water}" + componentMolarWeight="{44e-3, 18e-3}" + phasePVTParaFiles="{pvtgas.txt, pvtliquid.txt}" + flashModelParaFile="co2flash.txt"> + - + name="relperm" + phaseNames="{gas, water}" + phaseMinVolumeFraction="{0.0, 0.0}" + phaseRelPermExponent="{1.5, 1.5}" + phaseRelPermMaxValue="{0.9, 0.9}"> + - - + name="initialPressure" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="pressure" + scale="9e6"> + + name="initialTemperature" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="temperature" + scale="368.15"> + + name="initialComposition_co2" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="0" + scale="0.005"> + - + name="initialComposition_water" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="1" + scale="0.995"> + - - + name="vtkOutput"> + + name="sidreRestart"> + - + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/simpleCo2InjTutorial_base.xml b/inputFiles/compositionalMultiphaseWell/simpleCo2InjTutorial_base.xml index 705b4934fb9..edc2f004980 100644 --- a/inputFiles/compositionalMultiphaseWell/simpleCo2InjTutorial_base.xml +++ b/inputFiles/compositionalMultiphaseWell/simpleCo2InjTutorial_base.xml @@ -1,226 +1,216 @@ - - - - + name="coupledFlowAndWells" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + initialDt="1e2" + targetRegions="{reservoir, wellRegion}"> + newtonTol="1.0e-4" + lineSearchAction="None" + maxTimeStepCuts="10" + newtonMaxIter="40"> + + solverType="fgmres" + preconditionerType="mgr" + krylovTol="1e-5"> + - - + name="compositionalMultiphaseFlow" + targetRegions="{reservoir}" + discretization="fluidTPFA" + temperature="368.15" + maxCompFractionChange="0.2" + logLevel="1" + useMass="1"> + + name="compositionalMultiphaseWell" + targetRegions="{wellRegion}" + maxCompFractionChange="0.2" + logLevel="1" + useMass="1" + writeCSV="1"> + name="wellControls" + type="injector" + enableCrossflow="0" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71"> + + + + + - - - - + name="reservoir" + cellBlocks="{*}" + materialList="{fluid, rock, relperm}"> + + name="wellRegion" + materialList="{fluid}"> + - - - + name="fluidTPFA"> + - - - - + name="fluid" + phaseNames="{gas, water}" + componentNames="{co2, water}" + componentMolarWeight="{44e-3, 18e-3}" + phasePVTParaFiles="{pvtgas.txt, pvtliquid.txt}" + flashModelParaFile="co2flash.txt"> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + - + name="nullSolid"> + - + name="rockPorosity" + defaultReferencePorosity="0.05" + referencePressure="1.0e7" + compressibility="4.5e-10"> + - + name="relperm" + phaseNames="{gas, water}" + phaseMinVolumeFraction="{0.05, 0.30}" + phaseRelPermExponent="{2.0, 2.0}" + phaseRelPermMaxValue="{1.0, 1.0}"> + - + name="rockPerm" + permeabilityComponents="{1.0e-17, 1.0e-17, 3.0e-17}"> + - - - - - - + name="permx" + initialCondition="1" + component="0" + setNames="{all}" + objectPath="ElementRegions/reservoir" + fieldName="rockPerm_permeability" + scale="1e-15" + functionName="permxFunc"> + - + name="permy" + initialCondition="1" + component="1" + setNames="{all}" + objectPath="ElementRegions/reservoir" + fieldName="rockPerm_permeability" + scale="1e-15" + functionName="permyFunc"> + - + name="permz" + initialCondition="1" + component="2" + setNames="{all}" + objectPath="ElementRegions/reservoir" + fieldName="rockPerm_permeability" + scale="1.5e-15" + functionName="permzFunc"> + - + name="initialPressure" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/reservoir" + fieldName="pressure" + scale="1.25e7"> + + name="initialComposition_co2" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/reservoir" + fieldName="globalCompFraction" + component="0" + scale="0.0"> + + + - - - - + name="simpleReservoirViz"> + - + name="restartOutput"> + - + name="timeHistoryOutput" + sources="{/Tasks/wellPressureCollection}" + filename="wellPressureHistory"> + - - - - + name="wellPressureCollection" + objectPath="ElementRegions/wellRegion/wellRegionUniqueSubRegion" + fieldName="pressure"> + - - - - + + - - + + + interpolation="nearest"> + - - + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/staged_perf_base.xml b/inputFiles/compositionalMultiphaseWell/staged_perf_base.xml index 302d728e9b4..9e1b4a09e6e 100644 --- a/inputFiles/compositionalMultiphaseWell/staged_perf_base.xml +++ b/inputFiles/compositionalMultiphaseWell/staged_perf_base.xml @@ -1,198 +1,197 @@ - - + name="reservoirSystem" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="2" + targetRegions="{reservoir, wellRegion1}"> + newtonTol="1.0e-8" + logLevel="4" + lineSearchAction="None" + newtonMaxIter="40"> + + directParallel="0"> + - - + name="compositionalMultiphaseFlow" + logLevel="1" + discretization="fluidTPFA" + targetRegions="{reservoir}" + temperature="297.15"> + + name="compositionalMultiphaseWell" + logLevel="4" + writeCSV="1" + targetRegions="{wellRegion1}"> + name="wellControls1" + type="producer"> + + + + + - - - + name="compflowStatistics" + flowSolverName="compositionalMultiphaseFlow" + logLevel="1" + computeCFLNumbers="1" + computeRegionStatistics="1"> + - + maxTime="4.0e4"> + name="statistics" + timeFrequency="2e2" + target="/Tasks/compflowStatistics"> + - + name="solverApplications" + forceDt="2.5e3" + target="/Solvers/reservoirSystem"> + - + name="outputs" + timeFrequency="2.5e3" + target="/Outputs/vtkOutput"> + + name="restarts" + timeFrequency="1.25e4" + targetExactTimestep="0" + target="/Outputs/restartOutput"> + - + name="fluidTPFA"> + - - + name="reservoir" + cellBlocks="{*}" + materialList="{fluid, rock, relperm}"> + - + name="wellRegion1" + materialList="{fluid, relperm}"> + - - + name="fluid" + phaseNames="{gas, water}" + componentNames="{co2, water}" + componentMolarWeight="{44e-3, 18e-3}" + phasePVTParaFiles="{pvtgas.txt, pvtliquid.txt}" + flashModelParaFile="co2flash.txt"> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + - + name="nullSolid"> + - + name="rockPorosity" + defaultReferencePorosity="0.05" + referencePressure="0.0" + compressibility="1.0e-9"> + - + name="relperm" + phaseNames="{gas, water}" + phaseMinVolumeFraction="{0.1, 0.15}" + phaseRelPermExponent="{2.0, 2.0}" + phaseRelPermMaxValue="{0.8, 0.9}"> + + name="rockPerm" + permeabilityComponents="{2.0e-16, 2.0e-16, 2.0e-16}"> + - - + name="initialPressure" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/reservoir" + fieldName="pressure" + scale="1e6"> + - + name="initialComposition_co2" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/reservoir" + fieldName="globalCompFraction" + component="0" + scale="0.0"> + - + name="initialComposition_water" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/reservoir" + fieldName="globalCompFraction" + component="1" + scale="1.0"> + - + name="equil" + objectPath="ElementRegions" + datumElevation="0" + datumPressure="2.214e7" + initialPhaseName="water" + componentNames="{co2, water}" + componentFractionVsElevationTableNames="{initCO2CompFracTable, initWaterCompFracTable}" + temperatureVsElevationTableName="initTempTable"> + - - + coordinates="{-3000.0, 0.0}" + values="{0.0, 0.0}"> + - + coordinates="{-3000.0, 0.0}" + values="{1.0, 1.0}"> + - + coordinates="{-3000.0, 0.0}" + values="{368, 288}"> + - - + name="vtkOutput"> + + name="restartOutput"> + - + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_3d.xml b/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_3d.xml index 388b15ca605..5270d3bc94d 100644 --- a/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_3d.xml +++ b/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_3d.xml @@ -1,261 +1,265 @@ - - + name="reservoirSystem" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{Channel, wellRegion1, wellRegion2}"> + newtonTol="1.0e-8" + lineSearchAction="None" + newtonMaxIter="40"> + + directParallel="0"> + - - + name="compositionalMultiphaseFlow" + logLevel="1" + discretization="fluidTPFA" + targetRegions="{Channel}" + temperature="368.15" + maxCompFractionChange="0.2" + useMass="1"> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{wellRegion1, wellRegion2}" + maxCompFractionChange="0.2" + useMass="1" + writeCSV="1"> + name="wellControls1" + logLevel="1" + type="producer"> + + + + + + name="wellControls2" + logLevel="1" + type="injector"> + + + + + - - - - + name="mesh1" + elementTypes="{C3D8}" + xCoords="{0, 5, 10}" + yCoords="{0, 5, 10}" + zCoords="{0, 2.5, 5, 7.5, 10}" + nx="{5, 5}" + ny="{5, 5}" + nz="{3, 3, 3, 3}" + cellBlockNames="{cb-0_0_0, cb-1_0_0, cb-0_1_0, cb-1_1_0, cb-0_0_1, cb-1_0_1, cb-0_1_1, cb-1_1_1, + cb-0_0_2, cb-1_0_2, cb-0_1_2, cb-1_1_2, cb-0_0_3, cb-1_0_3, cb-0_1_3, cb-1_1_3}"> + name="well_producer1" + wellRegionName="wellRegion1" + wellControlsName="wellControls1" + polylineNodeCoords="{{9.5, 0.5, 12}, {9.5, 0.5, 0.05}}" + polylineSegmentConn="{{0, 1}}" + radius="0.1" + numElementsPerSegment="20"> + name="producer1_perf1" + distanceFromHead="11.95"> + - + name="well_injector1" + logLevel="1" + wellRegionName="wellRegion2" + wellControlsName="wellControls2" + polylineNodeCoords="{{9.5, 0.2, 12}, {9.5, 0.2, 9.5}}" + polylineSegmentConn="{{0, 1}}" + radius="0.1" + numElementsPerSegment="30"> + name="injector1_perf1" + distanceFromHead="2.45"> + - + maxTime="2.5e5"> - + name="outputs" + timeFrequency="5e4" + target="/Outputs/siloOutput"> + - + name="solverApplications" + forceDt="5e4" + target="/Solvers/reservoirSystem"> + + name="restarts" + timeFrequency="1.5e4" + targetExactTimestep="0" + target="/Outputs/restartOutput"> + - - + name="Channel" + cellBlocks="{cb-1_0_0, cb-0_0_0, cb-0_0_1, cb-0_1_1, cb-0_1_2, cb-1_1_2, cb-1_1_3, cb-1_0_3}" + materialList="{fluid1, rock, relperm, cappres, diffusion}"> + - + name="Barrier" + cellBlocks="{cb-0_1_0, cb-1_1_0, cb-1_1_1, cb-1_0_1, cb-1_0_2, cb-0_0_2, cb-0_0_3, cb-0_1_3}" + materialList="{}"> + - + name="wellRegion1" + materialList="{fluid1}"> + + name="wellRegion2" + materialList="{fluid1}"> + - + name="fluidTPFA"> + - - + name="fluid1" + phaseNames="{gas, water}" + componentNames="{co2, water}" + componentMolarWeight="{44e-3, 18e-3}" + phasePVTParaFiles="{pvtgas.txt, pvtliquid.txt}" + flashModelParaFile="co2flash.txt"> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + - + name="nullSolid"> + - + name="rockPorosity" + defaultReferencePorosity="0.1" + referencePressure="0.0" + compressibility="1.0e-9"> + - + name="relperm" + phaseNames="{gas, water}" + wettingNonWettingRelPermTableNames="{waterRelativePermeabilityTable, gasRelativePermeabilityTable}"> + - + name="cappres" + phaseNames="{gas, water}" + wettingNonWettingCapPressureTableName="waterCapillaryPressureTable"> + - + name="rockPerm" + permeabilityComponents="{2.0e-16, 2.0e-16, 2.0e-16}"> + - + name="diffusion" + phaseNames="{gas, water}" + defaultPhaseDiffusivityMultipliers="{20, 1}" + diffusivityComponents="{1e-9, 1e-9, 1e-9}"> + - - + name="initialPressure_channel" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Channel" + fieldName="pressure" + scale="9e6"> + - + name="initialComposition_co2" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Channel" + fieldName="globalCompFraction" + component="0" + scale="0.04"> + + name="initialComposition_water" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Channel" + fieldName="globalCompFraction" + component="1" + scale="0.96"> + - - + name="waterRelativePermeabilityTable" + coordinateFiles="{phaseVolFraction_water.txt}" + voxelFile="relPerm_water.txt"> + + name="gasRelativePermeabilityTable" + coordinateFiles="{phaseVolFraction_gas.txt}" + voxelFile="relPerm_gas.txt"> + + name="waterCapillaryPressureTable" + coordinateFiles="{phaseVolFraction_water.txt}" + voxelFile="capPres_water.txt"> + + name="phaseRateTable" + inputVarNames="{time}" + coordinates="{0, 5.01e4, 5e5}" + values="{1e-7, 2e-7, 2e-7}" + interpolation="lower"> + + name="totalRateTable" + inputVarNames="{time}" + coordinates="{0, 5.01e4, 5e5}" + values="{5e-8, 0, 0}" + interpolation="lower"> + - - - + name="siloOutput"> + + name="restartOutput"> + - + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml b/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml index b7e30e91dcb..fa6d76dd609 100644 --- a/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml +++ b/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml @@ -1,228 +1,235 @@ - - + name="reservoirSystem" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + initialDt="5e2" + targetRegions="{Channel, wellRegion1, wellRegion2}"> + newtonTol="1.0e-6" + newtonMaxIter="40"> + + directParallel="0"> + - - + name="compositionalMultiphaseFlow" + logLevel="1" + discretization="fluidHM" + targetRegions="{Channel}" + temperature="368.15" + targetRelativePressureChangeInTimeStep="1" + targetPhaseVolFractionChangeInTimeStep="1" + maxCompFractionChange="0.2" + maxRelativePressureChange="0.2" + useMass="1"> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{wellRegion1, wellRegion2}" + maxCompFractionChange="0.2" + maxRelativePressureChange="0.2" + useMass="1" + writeCSV="1"> + name="wellControls1" + type="producer"> + + + + + + name="wellControls2" + type="injector"> + + + + + - - - + name="mesh1" + file="staircase3d_tet_with_properties.vtu" + fieldsToImport="{FluidComposition, PERM, PORO}" + fieldNamesInGEOS="{globalCompFraction, rockPerm_permeability, rockPorosity_referencePorosity}" + partitionRefinement="1" + logLevel="2"> + name="well_producer1" + wellRegionName="wellRegion1" + wellControlsName="wellControls1" + polylineNodeCoords="{{9.5, 0.5, 12}, {9.5, 0.5, 0.05}}" + polylineSegmentConn="{{0, 1}}" + radius="0.1" + numElementsPerSegment="20"> + name="producer1_perf1" + distanceFromHead="11.95"> + - + name="well_injector1" + wellRegionName="wellRegion2" + wellControlsName="wellControls2" + polylineNodeCoords="{{9.5, 0.2, 12}, {9.5, 0.2, 9.5}}" + polylineSegmentConn="{{0, 1}}" + radius="0.1" + numElementsPerSegment="30"> + name="injector1_perf1" + distanceFromHead="2.45"> + - + maxTime="2.5e5"> - + name="outputs" + timeFrequency="5e4" + target="/Outputs/vtkOutput"> + - + name="solverApplications" + maxEventDt="5e4" + target="/Solvers/reservoirSystem"> + + name="restarts" + timeFrequency="1.5e4" + targetExactTimestep="0" + target="/Outputs/restartOutput"> + - - + name="Channel" + cellBlocks="{*}" + materialList="{fluid1, rock, relperm}"> + - + name="wellRegion1" + materialList="{fluid1}"> + + name="wellRegion2" + materialList="{fluid1}"> + - + name="fluidHM" + innerProductType="beiraoDaVeigaLipnikovManzini"> + - - + name="fluid1" + phaseNames="{gas, water}" + componentNames="{co2, water}" + componentMolarWeight="{44e-3, 18e-3}" + phasePVTParaFiles="{pvtgas.txt, pvtliquid.txt}" + flashModelParaFile="co2flash.txt"> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"> + - + name="nullSolid"> + - + name="rockPorosity" + defaultReferencePorosity="0.1" + referencePressure="0.0" + compressibility="1.0e-9"> + - + name="relperm" + phaseNames="{gas, water}" + phaseMinVolumeFraction="{0.05, 0.05}" + phaseRelPermExponent="{2, 1.5}" + phaseRelPermMaxValue="{0.8, 0.9}"> + + name="rockPerm" + permeabilityComponents="{2.0e-16, 2.0e-16, 2.0e-16}"> + - - + name="initialPressure_channel" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Channel" + fieldName="pressure" + scale="9e6"> + - + name="initialFacePressure_channel" + initialCondition="1" + setNames="{all}" + objectPath="faceManager" + fieldName="facePressure" + scale="9e6"> + - + name="initialComposition_co2" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Channel" + fieldName="globalCompFraction" + component="0" + scale="0.005"> + + name="initialComposition_water" + initialCondition="1" + setNames="{all}" + objectPath="ElementRegions/Channel" + fieldName="globalCompFraction" + component="1" + scale="0.995"> + - + name="totalRateTable" + inputVarNames="{time}" + coordinates="{0, 1.001e3, 3.5001e3, 5.001e3, 2.041e5, 1e6}" + values="{5e-7, 1e-7, 2e-7, 5e-7, 0, 0}" + interpolation="lower"> + - - + name="vtkOutput"> + + name="restartOutput"> + - + \ No newline at end of file diff --git a/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_fim.xml b/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_fim.xml index 0ca07929f8e..0e705cf7491 100644 --- a/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_fim.xml +++ b/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_fim.xml @@ -1,151 +1,160 @@ - - - - - - + + + - + name="reservoirSystem" + poromechanicsSolverName="multiphasePoroelasticity" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{channel, barrier, wellRegion1, wellRegion2}"> + newtonTol="1.0e-8" + lineSearchAction="None" + newtonMaxIter="40"> + + directParallel="0"> + - - + name="multiphasePoroelasticity" + solidSolverName="linearElasticity" + flowSolverName="twoPhaseFlow" + stabilizationType="Global" + stabilizationRegionNames="{channel}" + logLevel="1" + targetRegions="{channel}"> + - + name="linearElasticity" + logLevel="1" + discretization="FE1" + targetRegions="{channel, barrier}"> + - + name="twoPhaseFlow" + logLevel="1" + discretization="fluidTPFA" + targetRelativePressureChangeInTimeStep="1" + targetPhaseVolFractionChangeInTimeStep="1" + targetRegions="{channel}" + temperature="300" + useMass="1"> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{wellRegion1, wellRegion2}" + maxCompFractionChange="0.2" + useMass="1" + writeCSV="1"> + name="wellControls1" + logLevel="1" + type="producer"> + + + + + + name="wellControls2" + logLevel="1" + type="injector" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71"> + + + + + - - - + minTime="-1e11" + maxTime="1e7"> - + name="outputs" + timeFrequency="1e6" + target="/Outputs/vtkOutput"> + - + name="multiphasePoroelasticityEquilibrationStep" + targetTime="-1e11" + beginTime="-1e11" + target="/Tasks/multiphasePoroelasticityEquilibrationStep"> + + name="solverApplications1" + endTime="1e3" + target="/Solvers/reservoirSystem"> + - + name="solverApplications2" + beginTime="1e3" + maxEventDt="1e6" + target="/Solvers/reservoirSystem"> + + name="linearElasticityStatistics" + timeFrequency="1e6" + target="/Tasks/linearElasticityStatistics"> + - + name="twoPhaseFlowStatistics" + timeFrequency="1e6" + target="/Tasks/twoPhaseFlowStatistics"> + + name="restarts" + timeFrequency="5e6" + target="/Outputs/restartOutput"> + - + name="vtkOutput" + fieldNames="{initialPressure, skeletonChannel_density}"> + + name="restartOutput"> + - - + name="linearElasticityStatistics" + solidSolverName="linearElasticity" + logLevel="1"> + - - - + name="twoPhaseFlowStatistics" + flowSolverName="twoPhaseFlow" + logLevel="1" + computeCFLNumbers="1" + computeRegionStatistics="1"> + + + - - + \ No newline at end of file diff --git a/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_sequential.xml b/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_sequential.xml index e978595a49f..924662385d8 100755 --- a/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_sequential.xml +++ b/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_sequential.xml @@ -1,158 +1,168 @@ - - - - - - + + + - + name="reservoirSystem" + solidSolverName="linearElasticity" + reservoirAndWellsSolverName="reservoirAndWells" + logLevel="1" + targetRegions="{channel}"> + couplingType="Sequential" + subcycling="1" + newtonTol="1.0e-8" + lineSearchAction="None" + newtonMaxIter="100"> + + directParallel="0"> + - - + name="linearElasticity" + logLevel="1" + discretization="FE1" + targetRegions="{channel, barrier}"> + + name="reservoirAndWells" + flowSolverName="twoPhaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{channel, wellRegion1, wellRegion2}"> + newtonTol="1.0e-8" + lineSearchAction="None" + newtonMaxIter="40"> + + directParallel="0"> + - - + name="twoPhaseFlow" + logLevel="1" + discretization="fluidTPFA" + targetRelativePressureChangeInTimeStep="1" + targetPhaseVolFractionChangeInTimeStep="1" + targetRegions="{channel}" + temperature="300" + useMass="1"> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{wellRegion1, wellRegion2}" + maxCompFractionChange="0.2" + useMass="1" + writeCSV="1"> + name="wellControls1" + logLevel="1" + type="producer"> + + + + + + name="wellControls2" + logLevel="1" + type="injector" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71"> + + + + + - - - + minTime="-1e11" + maxTime="1e7"> - + name="outputs" + timeFrequency="1e6" + target="/Outputs/vtkOutput_seq"> + - + name="multiphasePoroelasticityEquilibrationStep" + targetTime="-1e11" + beginTime="-1e11" + target="/Tasks/multiphasePoroelasticityEquilibrationStep"> + + name="solverApplications1" + endTime="1e3" + target="/Solvers/reservoirSystem"> + - + name="solverApplications2" + beginTime="1e3" + maxEventDt="1e6" + target="/Solvers/reservoirSystem"> + + name="linearElasticityStatistics" + timeFrequency="1e6" + target="/Tasks/linearElasticityStatistics"> + - + name="twoPhaseFlowStatistics" + timeFrequency="1e6" + target="/Tasks/twoPhaseFlowStatistics"> + + name="restarts" + timeFrequency="5e6" + target="/Outputs/restartOutput"> + - + name="vtkOutput_seq" + fieldNames="{initialPressure, skeletonChannel_density}"> + + name="restartOutput"> + - - + name="linearElasticityStatistics" + solidSolverName="linearElasticity" + logLevel="1"> + - + name="twoPhaseFlowStatistics" + flowSolverName="twoPhaseFlow" + logLevel="1" + computeCFLNumbers="1" + computeRegionStatistics="1"> + - + logLevel="1" + name="multiphasePoroelasticityEquilibrationStep" + poromechanicsSolverName="reservoirSystem" + solidMechanicsStatisticsName="linearElasticityStatistics"> + - - + \ No newline at end of file diff --git a/scripts/convert_well_schema.py b/scripts/convert_well_schema.py new file mode 100644 index 00000000000..dab3b4ffc5a --- /dev/null +++ b/scripts/convert_well_schema.py @@ -0,0 +1,208 @@ +import xml.etree.ElementTree as ET +import os +import optparse + +def print_xml_with_indent_and_attributes(ofn,tree, indent=" "): + import textwrap + ofs = open(ofn,"w") + root = tree.getroot() + ET.indent(tree, space=indent, level=0) # Indent nested elements + + def format_element(elem, level=0): + spaces = indent * level + tag_line = f"{spaces}<{elem.tag}" + attrib_lines = [] + for k, v in elem.attrib.items(): + v =v.replace(" ","") + v = v.replace(",",", ") + attr_str = f'{k}="{v}"' + wrapped = textwrap.wrap(attr_str, width=100, break_long_words=False, break_on_hyphens=False) + for i, line in enumerate(wrapped): + if i == 0: + attrib_lines.append(f"{indent * (level + 1)}{indent}{line}") + else: + # Extra indent for all rows after the first + attrib_lines.append(f"{indent * (level + 2)}{" "+line}") + if attrib_lines: + tag_line += "\n" + "\n".join(attrib_lines) + tag_line += f">" + else: + istrt = tag_line.find("<") + if istrt > -1: + tag_line += ">" + else: + tag_line += ">" + lines = [tag_line] + if elem.text and elem.text.strip(): + lines.append(f"{spaces}{indent}{elem.text.strip()}") + for child in elem: + lines.append(format_element(child, level + 1)) + lines.append(f"{spaces}") + return "\n".join(lines) + ofs.write(format_element(root)) + ofs.close() + +def update_or_add_constraint_element(xml_file, ofs,delete_old_schema,add_we,estimatorSolves): + #tree = ET.parse(xml_file) + with open(xml_file, 'rb') as xml_file: + tree = ET.parse(xml_file) + root = tree.getroot() + compoFluidModel = True + for elem in root.iter(): + #print(f"Tag: {elem.tag}, Attributes: {elem.attrib}, Text: {elem.text}") + + if elem.tag == "CompositionalMultiphaseWell" or elem.tag == "SinglePhaseWell": + if elem.tag == "SinglePhaseWell": + compoFluidModel = False + if "writeCSV" not in elem.attrib: + esolves = '"'+str(estimatorSolves)+'"' + elem.set("writeCSV","1") + if add_we: + elem.set("useNewCode", "1") + nlsTag="NonlinearSolverParameters" + nlsAttributes={} + nlsAttributes["newtonTol"]="1.0e-8" + nlsAttributes["lineSearchAction"]="None" + nlsAttributes["newtonMaxIter"]="20" + elem.insert(0,ET.Element(nlsTag,nlsAttributes)) + lsTag="LinearSolverParamters" + lsAttributes={} + lsAttributes["directParallel"]="0" + elem.insert(0,ET.Element(lsTag,lsAttributes)) + + if elem.tag == "WellControls": + #print(f"Tag: {elem.tag}, Attributes: {elem.attrib}, Text: {elem.text}") + if "control" in elem.attrib: + if delete_old_schema: + elem.attrib.pop("control") + if add_we: + elem.set("estimateWellSolution",str(estimatorSolves)) + isProducer = elem.attrib['type'] == 'producer' + if isProducer: + constraintType="Production" + pressureType="Minimum" + else: + constraintType="Injection" + pressureType="Maximum" + # setup phase constraint + if 'targetPhaseName' in elem.attrib: + phaseConstraintTag= "Phase"+constraintType+"Constraint" + phaseConstraintAttributes={} + phaseConstraintAttributes["name"]="max"+elem.attrib['targetPhaseName'].lower() +"prod" if isProducer else "max"+elem.attrib['targetPhaseName'].lower() +"inj" + if 'targetPhaseName' in elem.attrib: + phaseConstraintAttributes["phaseName"] = elem.attrib['targetPhaseName'] + if delete_old_schema: + elem.attrib.pop("targetPhaseName") + if "targetPhaseRateTableName" in elem.attrib: + phaseConstraintAttributes["constraintScheduleTableName"]=elem.attrib["targetPhaseRateTableName"] + if delete_old_schema: + elem.attrib.pop("targetPhaseRateTableName") + elif "targetPhaseRate" in elem.attrib: + phaseConstraintAttributes["phaseRate"]=elem.attrib["targetPhaseRate"] + if delete_old_schema: + elem.attrib.pop("targetPhaseRate") + else: + print("error missing phase rate info") + if not isProducer: + if compoFluidModel: + if "injectionStream" in elem: + phaseConstraintAttributes["injectionStream"]=elem.attrib["injectionStream"] + phaseConstraintAttributes["injectionTemperature"]=elem.attrib["injectionTemperature"] + if delete_old_schema: + elem.attrib.pop("injectionStream") + elem.attrib.pop("injectionTemperature") + else: + print("error missinging injectionStream ",elem) + + + elem.append(ET.Element(phaseConstraintTag,phaseConstraintAttributes)) + + # setup pressure constraint + pressureConstraintTag= pressureType+"BHPConstraint" + pressureConstraintAttributes={} + pressureConstraintAttributes["name"]="minbhp" if isProducer else "maxbhp" + if 'targetBHPTableName' in elem.attrib: + pressureConstraintAttributes["constraintScheduleTableName"]=elem.attrib["targetBHPTableName"] + if delete_old_schema: + elem.attrib.pop("targetBHPTableName") + elif 'targetBHP' in elem.attrib: + pressureConstraintAttributes["targetBHP"]=elem.attrib["targetBHP"] + if delete_old_schema: + elem.attrib.pop("targetBHP") + else: + print('error missing bhp info') + + if 'referenceElevation' in elem.attrib: + pressureConstraintAttributes["referenceElevation"]=elem.attrib["referenceElevation"] + if delete_old_schema: + elem.attrib.pop("referenceElevation") + else: + print('error missing bhp referenceElevation') + + elem.append(ET.Element(pressureConstraintTag,pressureConstraintAttributes)) + + totalVolRateTag= "TotalVol"+constraintType+"Constraint" + totalVolRateAttributes={} + if 'targetTotalRate' in elem.attrib or 'targetTotalRateTableName' in elem.attrib: + if 'targetTotalRate' in elem.attrib: + totalVolRateAttributes["volumeRate"]=elem.attrib["targetTotalRate"] + if delete_old_schema: + elem.attrib.pop("targetTotalRate") + if 'targetTotalRateTableName' in elem.attrib: + totalVolRateAttributes["constraintScheduleTableName"]=elem.attrib["targetTotalRateTableName"] + if delete_old_schema: + elem.attrib.pop("targetTotalRateTableName") + if not isProducer: + if compoFluidModel: + totalVolRateAttributes["injectionStream"]=elem.attrib["injectionStream"] + totalVolRateAttributes["injectionTemperature"]=elem.attrib["injectionTemperature"] + if delete_old_schema: + elem.attrib.pop("injectionStream") + elem.attrib.pop("injectionTemperature") + elem.append(ET.Element(totalVolRateTag,totalVolRateAttributes)) + print_xml_with_indent_and_attributes(ofs,tree) + + +def main1(ifs,ofs,delete_old_schema,add_we,estimatorSolves): + update_or_add_constraint_element(ifs,ofs,delete_old_schema,add_we,estimatorSolves) + + +if __name__ == "__main__": + + bdir = "/Users/byer3/geos_models/geos-total-dataset/GreatNorthernLight/GNL_FlowOnly/depletion" + #fn = "/Users/byer3/opm/opm-simulators/tests/include/b1_vfp_flowline.inc" + ifn = 'GNL_BO_WELL_FULLRATE.xml' + ofn = 'GNL_BO_WELL_FULLRATE_WE2.xml' + #ofn="/Users/byer3/GEOS-DEV-1105/we0708/inputFiles/compositionalMultiphaseWell/include" + #main1(os.path.join(bdir,ifn),os.path.join(bdir,ofn)) + + parser = optparse.OptionParser() + parser.add_option("-s", "--sourcefile", type="str" ,default="", help="source file") + parser.add_option("-t", "--targetfile", type="str" ,default="", help="target file") + parser.add_option("-a", "--add", action="store_true",default=False, help="add we strings") + parser.add_option("-e", "--estimatorSolves", type="int" ,default=0, help="when to use estimator") + parser.add_option("-d", "--delete", action="store_true",default=False, help="delete old schema") + parser.add_option("-r", "--replace", action="store_true",default=False, help="in place substitution") + parser.add_option("-f", "--file", type="str" ,default="", help="file with list of files to process") + (options, args) = parser.parse_args() + if options.file: + ifs = open(options.file,"r") + for f in ifs: + options.sourcefile=f.rstrip().lstrip() + if options.replace: + fn1=f.rstrip().lstrip() + fn2=fn1 + else: + fn1 , fn2 = f.split() + fn1=fn1.rsplit().lsplit() + fn2=fn2.rsplit().lsplit() + print("Processing ",fn1,fn2,options.add,options.estimatorSolves) + main1(fn1,fn2,options.delete,options.add,options.estimatorSolves) + else: + if options.replace: + options.targetfile=options.sourcefile + main1(options.sourcefile,options.targetfile,options.delete,options.add,options.estimatorSolves) + + + + print('Finished') \ No newline at end of file From 292c90f6ba9f5fa3c4711a6a67a25fde37310050 Mon Sep 17 00:00:00 2001 From: Thomas James Byer Date: Wed, 15 Oct 2025 09:38:31 -0700 Subject: [PATCH 13/71] schema --- src/coreComponents/schema/schema.xsd | 47 ++-------------------- src/coreComponents/schema/schema.xsd.other | 4 +- 2 files changed, 6 insertions(+), 45 deletions(-) diff --git a/src/coreComponents/schema/schema.xsd b/src/coreComponents/schema/schema.xsd index c9b84e61719..7e7cac28c2f 100644 --- a/src/coreComponents/schema/schema.xsd +++ b/src/coreComponents/schema/schema.xsd @@ -3370,8 +3370,6 @@ When set to 2 also output convergence information to a csv--> - - @@ -3405,6 +3403,8 @@ Information output from lower logLevels is added with the desired log level + + @@ -3420,13 +3420,6 @@ When set to 2 also output convergence information to a csv--> - - @@ -3435,46 +3428,19 @@ When set to 2 also output convergence information to a csv--> - Injector pressure at reference depth initialized as: (1+initialPressureCoefficient)*reservoirPressureAtClosestPerforation + density*g*( zRef - zPerf ) - Producer pressure at reference depth initialized as: (1-initialPressureCoefficient)*reservoirPressureAtClosestPerforation + density*g*( zRef - zPerf ) --> - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -3486,11 +3452,6 @@ See note on referenceReservoirRegion for reservoir condition options--> - - - - - @@ -5165,8 +5126,6 @@ When set to 2 also output convergence information to a csv--> - - @@ -5188,6 +5147,8 @@ Information output from lower logLevels is added with the desired log level + + diff --git a/src/coreComponents/schema/schema.xsd.other b/src/coreComponents/schema/schema.xsd.other index 38ec3095e83..145c29f3c70 100644 --- a/src/coreComponents/schema/schema.xsd.other +++ b/src/coreComponents/schema/schema.xsd.other @@ -516,7 +516,7 @@ - + @@ -1502,7 +1502,7 @@ - + From d4eb50402e142303ce643f041442f0b11466ae9e Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Thu, 16 Oct 2025 15:45:07 -0700 Subject: [PATCH 14/71] 1)fixes for catalogue registration, 2) xml convert script still needs to fixed and inputFiles regenerated --- .../fluidFlow/wells/SinglePhaseWell.cpp | 2 +- .../fluidFlow/wells/WellBHPConstraints.cpp | 3 + .../fluidFlow/wells/WellBHPConstraints.hpp | 21 +- .../fluidFlow/wells/WellConstraintsBase.hpp | 5 + .../fluidFlow/wells/WellControls.cpp | 20 +- .../fluidFlow/wells/WellControls.hpp | 14 +- .../wells/WellInjectionConstraint.cpp | 19 +- .../wells/WellInjectionConstraint.hpp | 4 +- .../wells/WellProductionConstraint.cpp | 17 +- .../wells/WellProductionConstraint.hpp | 3 +- src/coreComponents/schema/schema.xsd | 232 +++++++++++++++--- src/coreComponents/schema/schema.xsd.other | 74 +++--- 12 files changed, 307 insertions(+), 107 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index 839fc616411..98d91cca41f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -407,7 +407,7 @@ void SinglePhaseWell::updateSeparator( WellElementSubRegion & subRegion ) geos::internal::kernelLaunchSelectorThermalSwitch( isThermal(), [&] ( auto ISTHERMAL ) { integer constexpr IS_THERMAL = ISTHERMAL(); - GEOS_UNUSED_VAR(IS_THERMAL); + GEOS_UNUSED_VAR( IS_THERMAL ); // bring everything back to host, capture the scalars by reference forAll< serialPolicy >( 1, [fluidSeparatorWrapper, pres, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.cpp index 1486362f296..70f6e79b86a 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.cpp @@ -110,4 +110,7 @@ bool MaximumBHPConstraint::checkViolation( WellConstraintBase const & currentCon return currentConstraint.bottomHolePressure() > getConstraintValue( currentTime ); } +REGISTER_CATALOG_ENTRY( WellConstraintBase, MinimumBHPConstraint, string const &, Group * const ) +REGISTER_CATALOG_ENTRY( WellConstraintBase, MaximumBHPConstraint, string const &, Group * const ) + } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp index 06a4121ddd7..3002d303e39 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellBHPConstraints.hpp @@ -83,7 +83,6 @@ class BHPConstraint : public WellConstraintBase ///@} - /** * @name Getters / Setters */ @@ -198,7 +197,15 @@ class MinimumBHPConstraint : public BHPConstraint ///@} - + /** + * @brief name of the node manager in the object catalog + * @return string that contains the catalog name to generate a new Constraint object through the object catalog. + */ + static string catalogName() + { + return "MinimumBHPConstraint"; + } + virtual string getCatalogName() const override { return catalogName(); } /** * @name Getters / Setters */ @@ -280,7 +287,15 @@ class MaximumBHPConstraint : public BHPConstraint ///@} - + /** + * @brief name of the node manager in the object catalog + * @return string that contains the catalog name to generate a new Constraint object through the object catalog. + */ + static string catalogName() + { + return "MaximumBHPConstraint"; + } + virtual string getCatalogName() const override { return catalogName(); } /** * @name Getters / Setters */ diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp index 4eaf2b82480..586f61a17d3 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp @@ -69,6 +69,11 @@ class WellConstraintBase : public dataRepository::Group /// Get the singleton catalog for WellConstraintBase static CatalogInterface::CatalogType & getCatalog(); + /** + * @brief function to return the catalog name of the derived class + * @return a string that contains the catalog name of the derived class + */ + virtual string getCatalogName() const = 0; /** * @name Constructor / Destructor */ diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index 6477de44973..6020aaedf33 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -126,45 +126,45 @@ Group * WellControls::createChild( string const & childKey, string const & child m_maxBHPConstraint = &bhpConstraint; constraint = &bhpConstraint; } - else if( childKey == viewKeyStruct::phaseProductionConstraintString() ) + else if( childKey == viewKeyStruct::productionPhaseVolumeRateConstraintString() ) { ProductionConstraint< PhaseVolumeRateConstraint > & phaseConstraint = registerGroup< ProductionConstraint< PhaseVolumeRateConstraint > >( childName ); m_productionRateConstraintList.emplace_back( &phaseConstraint ); constraint = &phaseConstraint; } - else if( childKey == viewKeyStruct::phaseInjectionConstraintString() ) + else if( childKey == viewKeyStruct::injectionPhaseVolumeRateConstraint() ) { InjectionConstraint< PhaseVolumeRateConstraint > & phaseConstraint = registerGroup< InjectionConstraint< PhaseVolumeRateConstraint > >( childName ); m_injectionRateConstraintList.emplace_back( &phaseConstraint ); constraint = &phaseConstraint; } - else if( childKey == viewKeyStruct::totalVolProductionConstraintString() ) + else if( childKey == viewKeyStruct::productionVolumeRateConstraint() ) { ProductionConstraint< VolumeRateConstraint > & volConstraint = registerGroup< ProductionConstraint< VolumeRateConstraint > >( childName ); m_productionRateConstraintList.emplace_back( &volConstraint ); constraint = &volConstraint; } - else if( childKey == viewKeyStruct::totalVolInjectionConstraintString() ) + else if( childKey == viewKeyStruct::injectionVolumeRateConstraint() ) { InjectionConstraint< VolumeRateConstraint > & volConstraint = registerGroup< InjectionConstraint< VolumeRateConstraint > >( childName ); m_injectionRateConstraintList.emplace_back( &volConstraint ); constraint = &volConstraint; } - else if( childKey == viewKeyStruct::massProductionConstraintString() ) + else if( childKey == viewKeyStruct::productionMassRateConstraint() ) { ProductionConstraint< MassRateConstraint > & massConstraint = registerGroup< ProductionConstraint< MassRateConstraint > >( childName ); m_productionRateConstraintList.emplace_back( &massConstraint ); constraint = &massConstraint; } - else if( childKey == viewKeyStruct::massInjectionConstraintString() ) + else if( childKey == viewKeyStruct::injectionMassRateConstraint() ) { InjectionConstraint< MassRateConstraint > & massConstraint = registerGroup< InjectionConstraint< MassRateConstraint > >( childName ); m_injectionRateConstraintList.emplace_back( &massConstraint ); constraint = &massConstraint; } - else if( childKey == viewKeyStruct::liquidProductionConstraintString() ) + else if( childKey == viewKeyStruct::productionLiquidRateConstraint() ) { ProductionConstraint< LiquidRateConstraint > & liquidConstraint = registerGroup< ProductionConstraint< LiquidRateConstraint > >( childName ); m_productionRateConstraintList.emplace_back( &liquidConstraint ); @@ -175,7 +175,11 @@ Group * WellControls::createChild( string const & childKey, string const & child void WellControls::expandObjectCatalogs() { - //createChild( keys::wellControls, keys::wellControls ); + // During schema generation, register one of each type derived from ConstitutiveBase here + for( auto & catalogIter: WellConstraintBase::getCatalog()) + { + createChild( catalogIter.first, catalogIter.first ); + } } namespace diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp index 17dd29aeea1..2bcb9aa6332 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp @@ -482,19 +482,19 @@ class WellControls : public dataRepository::Group /// string key for the maximum BHP presssure for a injection static constexpr char const * maximumBHPConstraintString() { return "MaximumBHPConstraint"; } /// string key for the maximum phase rate for a producer - static constexpr char const * phaseProductionConstraintString() { return "PhaseProductionConstraint"; } + static constexpr char const * productionPhaseVolumeRateConstraintString() { return "ProductionPhaseVolumeRateConstraint"; } /// string key for the maximum phase rate for a injection - static constexpr char const * phaseInjectionConstraintString() { return "PhaseInjectionConstraint"; } + static constexpr char const * injectionPhaseVolumeRateConstraint() { return "InjectionPhaseVolumeRateConstraint"; } /// string key for the maximum volume rate for a producer - static constexpr char const * totalVolProductionConstraintString() { return "TotalVolProductionConstraint"; } + static constexpr char const * productionVolumeRateConstraint() { return "ProductionVolumeRateConstraint"; } /// string key for the maximum volume rate for a injector - static constexpr char const * totalVolInjectionConstraintString() { return "TotalVolInjectionConstraint"; } + static constexpr char const * injectionVolumeRateConstraint() { return "InjectionVolumeRateConstraint"; } /// string key for the maximum mass rate for a producer - static constexpr char const * massProductionConstraintString() { return "massProductionConstraint"; } + static constexpr char const * productionMassRateConstraint() { return "ProductionMassRateConstraint"; } /// string key for the maximum mass rate for a injector - static constexpr char const * massInjectionConstraintString() { return "massInjectionConstraint"; } + static constexpr char const * injectionMassRateConstraint() { return "InjectionMassRateConstraint"; } /// string key for the liquid rate for a producer - static constexpr char const * liquidProductionConstraintString() { return "liquidProductionConstraint"; } + static constexpr char const * productionLiquidRateConstraint() { return "ProductionLiquidRateConstraint"; } } /// ViewKey struct for the WellControls class viewKeysWellControls; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellInjectionConstraint.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellInjectionConstraint.cpp index 708a8c088fa..57145a752dc 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellInjectionConstraint.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellInjectionConstraint.cpp @@ -30,6 +30,7 @@ namespace geos { +using namespace dataRepository; template< typename ConstraintRateType > InjectionConstraint< ConstraintRateType >::InjectionConstraint( string const & name, Group * const parent ) @@ -87,21 +88,21 @@ void InjectionConstraint< ConstraintRateType >::validateInjectionStream( ) } // Register concrete wrapper constraint types and instantiate templates. - -using LiquidInjectionConstraint = InjectionConstraint< LiquidRateConstraint >; -REGISTER_CATALOG_ENTRY( WellConstraintBase, LiquidInjectionConstraint, string const &, Group * const ) template class InjectionConstraint< LiquidRateConstraint >; +using InjectionLiquidRateConstraint = InjectionConstraint< LiquidRateConstraint >; +REGISTER_CATALOG_ENTRY( WellConstraintBase, InjectionLiquidRateConstraint, string const &, Group * const ) -using MassInjectionConstraint = InjectionConstraint< MassRateConstraint >; -REGISTER_CATALOG_ENTRY( WellConstraintBase, MassInjectionConstraint, string const &, Group * const ) template class InjectionConstraint< MassRateConstraint >; +using InjectionMassRateConstraint = InjectionConstraint< MassRateConstraint >; +REGISTER_CATALOG_ENTRY( WellConstraintBase, InjectionMassRateConstraint, string const &, Group * const ) -using PhaseInjectionConstraint = InjectionConstraint< PhaseVolumeRateConstraint >; -REGISTER_CATALOG_ENTRY( WellConstraintBase, PhaseInjectionConstraint, string const &, Group * const ) template class InjectionConstraint< PhaseVolumeRateConstraint >; +using InjectionPhaseVolumeRateConstraint = InjectionConstraint< PhaseVolumeRateConstraint >; +REGISTER_CATALOG_ENTRY( WellConstraintBase, InjectionPhaseVolumeRateConstraint, string const &, Group * const ) -using TotalVolInjectionConstraint = InjectionConstraint< VolumeRateConstraint >; -REGISTER_CATALOG_ENTRY( WellConstraintBase, TotalVolInjectionConstraint, string const &, Group * const ) template class InjectionConstraint< VolumeRateConstraint >; +using InjectionVolumeRateConstraint = InjectionConstraint< VolumeRateConstraint >; +REGISTER_CATALOG_ENTRY( WellConstraintBase, InjectionVolumeRateConstraint, string const &, Group * const ) + } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellInjectionConstraint.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellInjectionConstraint.hpp index 5e186534978..1707f5f20e7 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellInjectionConstraint.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellInjectionConstraint.hpp @@ -91,9 +91,11 @@ class InjectionConstraint : public ConstraintType */ static string catalogName() { - return "InjectionConstraint"+ConstraintType::catalogName(); + return "Injection"+ConstraintType::catalogName(); } + virtual string getCatalogName() const override { return catalogName(); } + struct injectionStreamKey { /// String key for the well injection stream diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellProductionConstraint.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellProductionConstraint.cpp index ce0a26f49b3..4ec3ec3299d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellProductionConstraint.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellProductionConstraint.cpp @@ -51,19 +51,20 @@ void ProductionConstraint< ConstraintRateType >::postInputInitialization() } // Register concrete wrapper constraint types and instantiate templates. -using LiquidProductionConstraint = ProductionConstraint< LiquidRateConstraint >; -REGISTER_CATALOG_ENTRY( WellConstraintBase, LiquidProductionConstraint, string const &, Group * const ) template class ProductionConstraint< LiquidRateConstraint >; +using ProductionLiquidRateConstraint = ProductionConstraint< LiquidRateConstraint >; +REGISTER_CATALOG_ENTRY( WellConstraintBase, ProductionLiquidRateConstraint, string const &, Group * const ) -using MassProductionConstraint = ProductionConstraint< MassRateConstraint >; -REGISTER_CATALOG_ENTRY( WellConstraintBase, MassProductionConstraint, string const &, Group * const ) template class ProductionConstraint< MassRateConstraint >; +using ProductionMassRateConstraint = ProductionConstraint< MassRateConstraint >; +REGISTER_CATALOG_ENTRY( WellConstraintBase, ProductionMassRateConstraint, string const &, Group * const ) -using PhaseProductionConstraint = ProductionConstraint< PhaseVolumeRateConstraint >; -REGISTER_CATALOG_ENTRY( WellConstraintBase, PhaseProductionConstraint, string const &, Group * const ) template class ProductionConstraint< PhaseVolumeRateConstraint >; +using ProductionPhaseVolumeRateConstraint = ProductionConstraint< PhaseVolumeRateConstraint >; +REGISTER_CATALOG_ENTRY( WellConstraintBase, ProductionPhaseVolumeRateConstraint, string const &, Group * const ) -using TotalVolProductionConstraint = ProductionConstraint< VolumeRateConstraint >; -REGISTER_CATALOG_ENTRY( WellConstraintBase, TotalVolProductionConstraint, string const &, Group * const ) template class ProductionConstraint< VolumeRateConstraint >; +using ProductionVolumeRateConstraint = ProductionConstraint< VolumeRateConstraint >; +REGISTER_CATALOG_ENTRY( WellConstraintBase, ProductionVolumeRateConstraint, string const &, Group * const ) + } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellProductionConstraint.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellProductionConstraint.hpp index ee8e8bbe031..ce1ca16de14 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellProductionConstraint.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellProductionConstraint.hpp @@ -89,8 +89,9 @@ class ProductionConstraint : public ConstraintType */ static string catalogName() { - return "ProductionConstraint"+ConstraintType::catalogName(); + return "Production"+ConstraintType::catalogName(); } + virtual string getCatalogName() const override { return catalogName(); } protected: virtual void postInputInitialization() override; diff --git a/src/coreComponents/schema/schema.xsd b/src/coreComponents/schema/schema.xsd index 7e7cac28c2f..7d5850a4553 100644 --- a/src/coreComponents/schema/schema.xsd +++ b/src/coreComponents/schema/schema.xsd @@ -222,18 +222,10 @@ - - - - - - - - @@ -1433,26 +1425,10 @@ stress - traction is applied to the faces as specified by the inner product of i - - - - - - - - - - - - - - - - @@ -1461,18 +1437,6 @@ stress - traction is applied to the faces as specified by the inner product of i - - - - - - - - - - - - @@ -3362,7 +3326,44 @@ When set to 2 also output convergence information to a csv--> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3420,6 +3421,17 @@ When set to 2 also output convergence information to a csv--> + + + + + + + + + + + @@ -3452,6 +3464,109 @@ See note on referenceReservoirRegion for reservoir condition options--> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3846,7 +3961,7 @@ Information output from lower logLevels is added with the desired log level - + @@ -3874,7 +3989,7 @@ When set to 2 also output convergence information to a csv--> - + @@ -5118,7 +5233,44 @@ When set to 2 also output convergence information to a csv--> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/coreComponents/schema/schema.xsd.other b/src/coreComponents/schema/schema.xsd.other index 145c29f3c70..40d6f1dece0 100644 --- a/src/coreComponents/schema/schema.xsd.other +++ b/src/coreComponents/schema/schema.xsd.other @@ -341,15 +341,11 @@ - - - - @@ -516,7 +512,7 @@ - + @@ -842,9 +838,29 @@ + + + + + + + + + + + + + + + + + + + + @@ -1502,7 +1518,7 @@ - + @@ -3275,7 +3291,7 @@ - + @@ -3303,7 +3319,7 @@ - + @@ -3322,11 +3338,11 @@ - + - + @@ -3336,7 +3352,7 @@ - + @@ -3346,11 +3362,11 @@ - + - + @@ -3360,7 +3376,7 @@ - + @@ -3370,7 +3386,7 @@ - + @@ -3380,7 +3396,7 @@ - + @@ -3404,7 +3420,7 @@ - + @@ -3422,7 +3438,7 @@ - + @@ -3434,7 +3450,7 @@ - + @@ -3446,7 +3462,7 @@ - + @@ -3454,11 +3470,11 @@ - + - + @@ -3481,7 +3497,7 @@ - + @@ -3507,7 +3523,7 @@ - + @@ -3528,7 +3544,7 @@ - + @@ -3558,7 +3574,7 @@ - + @@ -3572,7 +3588,7 @@ - + @@ -3603,7 +3619,7 @@ - + @@ -3648,7 +3664,7 @@ - + From bd3d0cff6a55c27419fdff7826471c3c593ff55d Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Mon, 20 Oct 2025 13:58:49 -0700 Subject: [PATCH 15/71] fix liq rate schema --- .../fluidFlow/wells/WellLiquidRateConstraint.cpp | 8 +++----- src/coreComponents/schema/schema.xsd | 4 ++-- src/coreComponents/schema/schema.xsd.other | 4 ++-- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.cpp index dab8b969486..54424d9224e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.cpp @@ -39,11 +39,9 @@ LiquidRateConstraint::LiquidRateConstraint( string const & name, Group * const p setDescription( "Phase rate, (if useSurfaceCondSitions: [surface m^3/s]; else [reservoir m^3/s]) " ); this->registerWrapper( viewKeyStruct::phaseNamesString(), &m_phaseNames ). - setRTTypeName( rtTypes::CustomTypes::groupNameRef ). - setDefaultValue( "" ). - setInputFlag( InputFlags::OPTIONAL ). - setRestartFlags( RestartFlags::WRITE_AND_READ ). - setDescription( "Name of the target phases" ); + setRTTypeName( rtTypes::CustomTypes::groupNameRefArray ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "List of fluid phase names defining the liquid" ); } LiquidRateConstraint::~LiquidRateConstraint() diff --git a/src/coreComponents/schema/schema.xsd b/src/coreComponents/schema/schema.xsd index 7d5850a4553..c9691664200 100644 --- a/src/coreComponents/schema/schema.xsd +++ b/src/coreComponents/schema/schema.xsd @@ -3533,8 +3533,8 @@ See note on referenceReservoirRegion for reservoir condition options--> - - + + diff --git a/src/coreComponents/schema/schema.xsd.other b/src/coreComponents/schema/schema.xsd.other index 40d6f1dece0..f18dcf97336 100644 --- a/src/coreComponents/schema/schema.xsd.other +++ b/src/coreComponents/schema/schema.xsd.other @@ -512,7 +512,7 @@ - + @@ -1518,7 +1518,7 @@ - + From 723c2bca35f57c423cb61b9f2139c90fed44bf4d Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 21 Oct 2025 10:36:26 -0700 Subject: [PATCH 16/71] Revert "1) well constraint schema script, 2) converted xmls, 3) Failed convert compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml" This reverts commit fa61ab139def5ae6ffcc2c4e861a7681c767bc15. --- .../1D_100cells/1D_benchmark.xml | 688 ++++++++--------- .../soreideWhitson/1D_100cells/1D_smoke.xml | 688 ++++++++--------- .../class09_pb3_drainageOnly_direct_base.xml | 324 ++++---- ...lass09_pb3_drainageOnly_iterative_base.xml | 421 +++++------ .../class09_pb3_hystRelperm_direct_base.xml | 347 +++++---- ...class09_pb3_hystRelperm_iterative_base.xml | 364 +++++---- .../benchmarks/Egg/deadOilEgg_base_direct.xml | 688 ++++++++--------- .../Egg/deadOilEgg_base_iterative.xml | 692 ++++++++---------- .../black_oil_wells_saturated_3d.xml | 475 ++++++------ .../black_oil_wells_saturated_3d_stone2.xml | 488 ++++++------ .../black_oil_wells_unsaturated_3d.xml | 405 +++++----- .../black_oil_wells_unsaturated_3d_stone2.xml | 525 +++++++------ .../compositional_multiphase_wells_1d.xml | 354 +++++---- .../compositional_multiphase_wells_2d.xml | 433 ++++++----- .../dead_oil_wells_2d.xml | 468 ++++++------ .../dead_oil_wells_hybrid_2d.xml | 438 ++++++----- .../isothm_mass_inj_table.xml | 349 +++++---- .../isothm_vol_inj_table.xml | 360 +++++---- .../simpleCo2InjTutorial_base.xml | 334 +++++---- .../staged_perf_base.xml | 285 ++++---- .../staircase_co2_wells_3d.xml | 398 +++++----- .../staircase_co2_wells_hybrid_3d.xml | 347 +++++---- .../PoroElastic_staircase_co2_3d_fim.xml | 247 +++---- ...oroElastic_staircase_co2_3d_sequential.xml | 254 +++---- scripts/convert_well_schema.py | 208 ------ 25 files changed, 4991 insertions(+), 5589 deletions(-) delete mode 100644 scripts/convert_well_schema.py diff --git a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml index 407ed2ab5e4..89b9cc7dc86 100644 --- a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml +++ b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml @@ -1,396 +1,294 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml index 4c97d038692..19a577bde98 100644 --- a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml +++ b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml @@ -1,396 +1,294 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_direct_base.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_direct_base.xml index 36005f1a47a..f2c31503e8a 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_direct_base.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_direct_base.xml @@ -1,207 +1,201 @@ + + + + + name="coupledFlowAndWells" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + initialDt="1e2" + targetRegions="{ reservoir, wellRegion }"> - + newtonTol="1.0e-3" + newtonMaxIter="12"/> - + directParallel="0"/> + - + name="compositionalMultiphaseFlow" + targetRegions="{ reservoir }" + discretization="fluidTPFA" + temperature="363" + maxCompFractionChange="0.2" + logLevel="1" + useMass="1"/> + + name="compositionalMultiphaseWell" + targetRegions="{ wellRegion }" + logLevel="1" + useMass="1"> - - - - - + name="wellControls" + type="injector" + control="totalVolRate" + referenceElevation="-3000" + targetBHP="1e8" + enableCrossflow="0" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71" + targetTotalRateTableName="totalRateTable" + injectionTemperature="353.15" + injectionStream="{ 1.0, 0.0 }"/> + - + name="reservoir" + cellBlocks="{ * }" + materialList="{ fluid, rock, relperm, cappres }"/> + - + name="wellRegion" + materialList="{ fluid }"/> + - + name="fluidTPFA" /> + - + name="fluid" + phaseNames="{ gas, water }" + componentNames="{ co2, water }" + componentMolarWeight="{ 44e-3, 18e-3 }" + phasePVTParaFiles="{ tables/pvtgas.txt, tables/pvtliquid_ez.txt }" + flashModelParaFile="tables/co2flash.txt"/> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> - + name="nullSolid"/> - + name="rockPorosity" + defaultReferencePorosity="0.1" + referencePressure="1.0e7" + compressibility="4.5e-10"/> - + name="rockPerm" + permeabilityComponents="{ 1.0e-12, 1.0e-12, 1.0e-12 }"/> + - + name="relperm" + phaseNames="{ gas, water }" + wettingNonWettingRelPermTableNames="{ waterRelativePermeabilityTable, + gasRelativePermeabilityTable }"/> + - + name="cappres" + phaseNames="{ gas, water }" + wettingNonWettingCapPressureTableName="waterCapillaryPressureTable"/> + - - + + + - + name="bcPressure" + objectPath="faceManager" + setNames="{ xpos, xneg, ypos, yneg }" + fieldName="pressure" + functionName="pressureFunction" + scale="1"/> - + name="bcTemperature" + objectPath="faceManager" + setNames="{ xpos, xneg, ypos, yneg }" + fieldName="temperature" + functionName="temperatureFunction" + scale="1"/> - + name="bcCompositionCO2" + objectPath="faceManager" + setNames="{ xpos, xneg, ypos, yneg }" + fieldName="globalCompFraction" + component="0" + scale="0.000001"/> - + name="bcCompositionWater" + objectPath="faceManager" + setNames="{ xpos, xneg, ypos, yneg }" + fieldName="globalCompFraction" + component="1" + scale="0.999999"/> + + - + name="initCO2CompFracTable" + coordinates="{ -3238.2, -2506.13 }" + values="{ 0.000001, 0.000001 }"/> - + name="initWaterCompFracTable" + coordinates="{ -3238.2, -2506.13 }" + values="{ 0.999999, 0.999999 }"/> + + - + name="waterRelativePermeabilityTable" + coordinateFiles="{ tables/phaseVolumeFraction_water.txt }" + voxelFile="tables/relPerm_water.txt"/> - + name="gasRelativePermeabilityTable" + coordinateFiles="{ tables/phaseVolumeFraction_gas.txt }" + voxelFile="tables/relPerm_gas.txt"/> + + + + + + + - - - - - - - - - + name="totalRateTable" + inputVarNames="{time}" + coordinates="{0, 7.7198e8, 1.544e9}" + values="{ 8.02849025, 0, 0}" + interpolation="lower"/> + - \ No newline at end of file + + diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_iterative_base.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_iterative_base.xml index e0eabc6d0da..8e76b08905b 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_iterative_base.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_iterative_base.xml @@ -1,252 +1,259 @@ + + + + + + name="coupledFlowAndWells" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + initialDt="1e2" + targetRegions="{ reservoir, wellRegion }"> - + newtonTol="1.0e-5" + newtonMaxIter="40"/> - + solverType="fgmres" + preconditionerType="mgr" + krylovTol="1e-6" + logLevel="1"/> + + + - + name="compositionalMultiphaseFlow" + targetRegions="{ reservoir }" + discretization="fluidTPFA" + temperature="363" + maxCompFractionChange="0.2" + logLevel="1" + useMass="1"/> + + + + name="compositionalMultiphaseWell" + targetRegions="{ wellRegion }" + logLevel="1" + useMass="1"> - - - - - + name="wellControls" + logLevel="1" + type="injector" + control="totalVolRate" + referenceElevation="-3000" + targetBHP="1e8" + enableCrossflow="0" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71" + targetTotalRateTableName="totalRateTable" + injectionTemperature="353.15" + injectionStream="{ 1.0, 0.0 }"/> - - - + name="MAX_MASS_INJ" + logLevel="1" + type="injector" + control="massRate" + referenceElevation="-3000" + targetBHP="1e8" + enableCrossflow="0" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71" + targetMassRate="15" + injectionTemperature="353.15" + injectionStream="{ 1.0, 0.0 }"/> - - - + name="MAX_MASS_INJ_TABLE" + logLevel="1" + type="injector" + control="massRate" + referenceElevation="-3000" + targetBHP="1e8" + enableCrossflow="0" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71" + targetMassRateTableName="totalMassTable" + injectionTemperature="353.15" + injectionStream="{ 1.0, 0.0 }"/> + + + - + name="reservoir" + cellBlocks="{ * }" + materialList="{ fluid, rock, relperm, cappres }"/> + - + name="wellRegion" + materialList="{ fluid }"/> + + - + name="fluidTPFA" /> + + - + name="fluid" + phaseNames="{ gas, water }" + componentNames="{ co2, water }" + componentMolarWeight="{ 44e-3, 18e-3 }" + phasePVTParaFiles="{ tables/pvtgas.txt, tables/pvtliquid_ez.txt }" + flashModelParaFile="tables/co2flash.txt"/> + + + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> - + name="nullSolid"/> - + name="rockPorosity" + defaultReferencePorosity="0.1" + referencePressure="1.0e7" + compressibility="4.5e-10"/> - + name="rockPerm" + permeabilityComponents="{ 1.0e-12, 1.0e-12, 1.0e-12 }"/> + + + - + name="relperm" + phaseNames="{ gas, water }" + wettingNonWettingRelPermTableNames="{ waterRelativePermeabilityTable, + gasRelativePermeabilityTable }"/> + + + - + name="cappres" + phaseNames="{ gas, water }" + wettingNonWettingCapPressureTableName="waterCapillaryPressureTable"/> + + - - + + + + + + + - + name="bcPressure" + objectPath="faceManager" + setNames="{3}" + fieldName="pressure" + functionName="pressureFunction" + scale="1"/> - + name="bcTemperature" + objectPath="faceManager" + setNames="{3}" + fieldName="temperature" + functionName="temperatureFunction" + scale="1"/> - + name="bcCompositionCO2" + objectPath="faceManager" + setNames="{3}" + fieldName="globalCompFraction" + component="0" + scale="0.000001"/> - + name="bcCompositionWater" + objectPath="faceManager" + setNames="{3}" + fieldName="globalCompFraction" + component="1" + scale="0.999999"/> + + - - - - - - - - - + name="initCO2CompFracTable" + coordinates="{ -3238.2, -2506.13 }" + values="{ 0.000001, 0.000001 }"/> - + name="initWaterCompFracTable" + coordinates="{ -3238.2, -2506.13 }" + values="{ 0.999999, 0.999999 }"/> + + - + name="waterRelativePermeabilityTable" + coordinateFiles="{ tables/phaseVolumeFraction_water.txt }" + voxelFile="tables/relPerm_water.txt"/> - + name="gasRelativePermeabilityTable" + coordinateFiles="{ tables/phaseVolumeFraction_gas.txt }" + voxelFile="tables/relPerm_gas.txt"/> + + + + + + + - + name="totalRateTable" + inputVarNames="{time}" + coordinates="{0, 7.7198e8, 1.544e9}" + values="{ 8.02849025 , 0, 0}" + interpolation="lower"/> + - + name="totalMassTable" + inputVarNames="{time}" + coordinates="{0, 7.7198e8, 1.544e9}" + values="{ 15 , 0, 0}" + interpolation="lower"/> - \ No newline at end of file + + diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_direct_base.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_direct_base.xml index 0d1f7ddccb3..c731abcf696 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_direct_base.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_direct_base.xml @@ -1,220 +1,215 @@ + + + + + name="coupledFlowAndWells" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + initialDt="1e2" + targetRegions="{ reservoir, wellRegion }"> - + newtonTol="1.0e-3" + newtonMaxIter="12"/> - + directParallel="0"/> + - + name="compositionalMultiphaseFlow" + targetRegions="{ reservoir }" + discretization="fluidTPFA" + temperature="363" + maxCompFractionChange="0.2" + logLevel="1" + useMass="1"/> + + name="compositionalMultiphaseWell" + targetRegions="{ wellRegion }" + logLevel="1" + useMass="1"> - - - - - + name="wellControls" + type="injector" + control="totalVolRate" + referenceElevation="-3000" + targetBHP="1e8" + enableCrossflow="0" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71" + targetTotalRateTableName="totalRateTable" + injectionTemperature="353.15" + injectionStream="{ 1.0, 0.0 }"/> + - + name="reservoir" + cellBlocks="{ * }" + materialList="{ fluid, rock, relperm, cappres }"/> + - + name="wellRegion" + materialList="{ fluid }"/> + - + name="fluidTPFA" /> + - + name="fluid" + phaseNames="{ gas, water }" + componentNames="{ co2, water }" + componentMolarWeight="{ 44e-3, 18e-3 }" + phasePVTParaFiles="{ tables/pvtgas.txt, tables/pvtliquid_ez.txt }" + flashModelParaFile="tables/co2flash.txt"/> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> - + name="nullSolid"/> - + name="rockPorosity" + defaultReferencePorosity="0.1" + referencePressure="1.0e7" + compressibility="4.5e-10"/> - + name="rockPerm" + permeabilityComponents="{ 1.0e-12, 1.0e-12, 1.0e-12 }"/> + + - + name="relperm" + phaseNames="{ gas, water }" + drainageWettingNonWettingRelPermTableNames="{ drainageWaterRelativePermeabilityTable, + drainageGasRelativePermeabilityTable }" + imbibitionNonWettingRelPermTableName="imbibitionGasRelativePermeabilityTable" + imbibitionWettingRelPermTableName="imbibitionWaterRelativePermeabilityTable"/> + - + name="cappres" + phaseNames="{ gas, water }" + wettingNonWettingCapPressureTableName="waterCapillaryPressureTable"/> + - - + + + + + - + name="bcPressure" + objectPath="faceManager" + setNames="{ xpos, xneg, ypos, yneg }" + fieldName="pressure" + functionName="pressureFunction" + scale="1"/> - + name="bcTemperature" + objectPath="faceManager" + setNames="{ xpos, xneg, ypos, yneg }" + fieldName="temperature" + functionName="temperatureFunction" + scale="1"/> - + name="bcCompositionCO2" + objectPath="faceManager" + setNames="{ xpos, xneg, ypos, yneg }" + fieldName="globalCompFraction" + component="0" + scale="0.000001"/> - + name="bcCompositionWater" + objectPath="faceManager" + setNames="{ xpos, xneg, ypos, yneg }" + fieldName="globalCompFraction" + component="1" + scale="0.999999"/> + + - + name="initCO2CompFracTable" + coordinates="{ -3238.2, -2506.13 }" + values="{ 0.000001, 0.000001 }"/> - + name="initWaterCompFracTable" + coordinates="{ -3238.2, -2506.13 }" + values="{ 0.999999, 0.999999 }"/> - + name="initTempTable" + coordinates="{ -3238.2, -2506.13 }" + values="{ 380.296, 358.334 }"/> + + + + + + + - + name="totalRateTable" + inputVarNames="{time}" + coordinates="{0, 7.7198e8, 1.544e9}" + values="{ 8.02849025, 0, 0}" + interpolation="lower"/> + + + - + name="drainageGasRelativePermeabilityTable" + coordinateFiles="{ tables/drainagePhaseVolFraction_gas.txt }" + voxelFile="tables/drainageRelPerm_gas.txt"/> - + name="imbibitionWaterRelativePermeabilityTable" + coordinateFiles="{ tables/imbibitionPhaseVolFraction_water.txt }" + voxelFile="tables/imbibitionRelPerm_water.txt"/> - - - - - - - - - + name="imbibitionGasRelativePermeabilityTable" + coordinateFiles="{ tables/imbibitionPhaseVolFraction_gas.txt }" + voxelFile="tables/imbibitionRelPerm_gas.txt"/> + - \ No newline at end of file + + diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_iterative_base.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_iterative_base.xml index bf0e54bfddf..ee1af0ef88d 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_iterative_base.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_iterative_base.xml @@ -1,234 +1,228 @@ + + + + + name="coupledFlowAndWells" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + initialDt="1e2" + targetRegions="{ reservoir, wellRegion }"> - + newtonTol="1.0e-3" + newtonMaxIter="12"/> - + solverType="fgmres" + preconditionerType="mgr" + krylovTol="1e-6" + logLevel="1"/> + - + name="compositionalMultiphaseFlow" + targetRegions="{ reservoir }" + discretization="fluidTPFA" + temperature="363" + maxCompFractionChange="0.2" + logLevel="1" + useMass="1"/> + + name="compositionalMultiphaseWell" + targetRegions="{ wellRegion }" + logLevel="1" + useMass="1"> - - - - - + name="wellControls" + type="injector" + logLevel="1" + control="totalVolRate" + referenceElevation="-3000" + targetBHP="1e8" + enableCrossflow="0" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71" + targetTotalRateTableName="totalRateTable" + injectionTemperature="353.15" + injectionStream="{ 1.0, 0.0 }"/> + - + name="reservoir" + cellBlocks="{ * }" + materialList="{ fluid, rock, relperm, cappres }"/> + - + name="wellRegion" + materialList="{ fluid }"/> + - + name="fluidTPFA" /> + - + name="fluid" + phaseNames="{ gas, water }" + componentNames="{ co2, water }" + componentMolarWeight="{ 44e-3, 18e-3 }" + phasePVTParaFiles="{ tables/pvtgas.txt, tables/pvtliquid_ez.txt }" + flashModelParaFile="tables/co2flash.txt"/> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> - + name="nullSolid"/> - + name="rockPorosity" + defaultReferencePorosity="0.1" + referencePressure="1.0e7" + compressibility="4.5e-10"/> - + name="rockPerm" + permeabilityComponents="{ 1.0e-12, 1.0e-12, 1.0e-12 }"/> + + + - + name="relperm" + phaseNames="{ gas, water }" + drainageWettingNonWettingRelPermTableNames="{ drainageWaterRelativePermeabilityTable, + drainageGasRelativePermeabilityTable }" + imbibitionNonWettingRelPermTableName="imbibitionGasRelativePermeabilityTable" + imbibitionWettingRelPermTableName="imbibitionWaterRelativePermeabilityTable"/> + + - + name="cappres" + phaseNames="{ gas, water }" + wettingNonWettingCapPressureTableName="waterCapillaryPressureTable"/> + - + name="equil" + objectPath="ElementRegions" + datumElevation="-3000" + datumPressure="3.0e7" + initialPhaseName="water" + componentNames="{ co2, water }" + componentFractionVsElevationTableNames="{ initCO2CompFracTable, + initWaterCompFracTable }" + temperatureVsElevationTableName="initTempTable"/> + + - + name="bcPressure" + objectPath="faceManager" + setNames="{3}" + fieldName="pressure" + functionName="pressureFunction" + scale="1"/> - + name="bcTemperature" + objectPath="faceManager" + setNames="{3}" + fieldName="temperature" + functionName="temperatureFunction" + scale="1"/> - + name="bcCompositionCO2" + objectPath="faceManager" + setNames="{3}" + fieldName="globalCompFraction" + component="0" + scale="0.000001"/> - + name="bcCompositionWater" + objectPath="faceManager" + setNames="{3}" + fieldName="globalCompFraction" + component="1" + scale="0.999999"/> + + - - - - - + name="initCO2CompFracTable" + coordinates="{ -3238.2, -2506.13 }" + values="{ 0.000001, 0.000001 }"/> - + name="initWaterCompFracTable" + coordinates="{ -3238.2, -2506.13 }" + values="{ 0.999999, 0.999999 }"/> - + name="initTempTable" + coordinates="{ -3238.2, -2506.13 }" + values="{ 380.296, 358.334 }"/> + - + name="waterRelativePermeabilityTable" + coordinateFiles="{ tables/phaseVolumeFraction_water.txt }" + voxelFile="tables/relPerm_water.txt"/> - + name="gasRelativePermeabilityTable" + coordinateFiles="{ tables/phaseVolumeFraction_gas.txt }" + voxelFile="tables/relPerm_gas.txt"/> + - + name="waterCapillaryPressureTable" + coordinateFiles="{ tables/phaseVolumeFraction_water.txt }" + voxelFile="tables/capPres_water.txt"/> + + + + + - + name="totalRateTable" + inputVarNames="{time}" + coordinates="{0, 7.7198e8, 1.544e9}" + values="{ 8.02849025, 0, 0}" + interpolation="lower"/> + + - + name="drainageWaterRelativePermeabilityTable" + coordinateFiles="{ tables/drainagePhaseVolFraction_water.txt }" + voxelFile="tables/drainageRelPerm_water.txt"/> - + name="drainageGasRelativePermeabilityTable" + coordinateFiles="{ tables/drainagePhaseVolFraction_gas.txt }" + voxelFile="tables/drainageRelPerm_gas.txt"/> - + name="imbibitionWaterRelativePermeabilityTable" + coordinateFiles="{ tables/imbibitionPhaseVolFraction_water.txt }" + voxelFile="tables/imbibitionRelPerm_water.txt"/> - + name="imbibitionGasRelativePermeabilityTable" + coordinateFiles="{ tables/imbibitionPhaseVolFraction_gas.txt }" + voxelFile="tables/imbibitionRelPerm_gas.txt"/> + - \ No newline at end of file + + diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml index ee697474dcf..048e88999d7 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml @@ -1,448 +1,404 @@ + + + + name="coupledFlowAndWells" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + initialDt="1e4" + targetRegions="{ reservoir, wellRegion1, wellRegion2, wellRegion3, wellRegion4, wellRegion5, wellRegion6, wellRegion7, wellRegion8, wellRegion9, wellRegion10, wellRegion11, wellRegion12 }"> - + newtonTol="1.0e-4" + newtonMaxIter="25" + timeStepDecreaseIterLimit="0.9" + timeStepIncreaseIterLimit="0.6" + timeStepCutFactor="0.1" + maxTimeStepCuts="10" + lineSearchAction="None"/> - + solverType="direct" + directParallel="0"/> + - + name="compositionalMultiphaseFlow" + targetRegions="{ reservoir }" + discretization="fluidTPFA" + temperature="297.15" + targetRelativePressureChangeInTimeStep="1" + targetPhaseVolFractionChangeInTimeStep="1" + maxCompFractionChange="0.3" + logLevel="1" + useMass="1"/> + + name="compositionalMultiphaseWell" + targetRegions="{ wellRegion1, wellRegion2, wellRegion3, wellRegion4, wellRegion5, wellRegion6, wellRegion7, wellRegion8, wellRegion9, wellRegion10, wellRegion11, wellRegion12 }" + maxCompFractionChange="0.5" + logLevel="1" + useMass="1"> - - - - - + name="wellControls1" + type="producer" + control="BHP" + referenceElevation="28" + targetBHP="3.9e7" + targetPhaseRate="1e6" + targetPhaseName="oil"/> - - - - - + name="wellControls2" + type="producer" + control="BHP" + referenceElevation="28" + targetBHP="3.9e7" + targetPhaseRate="1e6" + targetPhaseName="oil"/> + + + - - - - - + name="wellControls3" + type="producer" + control="BHP" + referenceElevation="28" + targetBHP="3.9e7" + targetPhaseRate="1e6" + targetPhaseName="oil"/> - - - - - + name="wellControls4" + type="producer" + control="BHP" + referenceElevation="28" + targetBHP="3.9e7" + targetPhaseRate="1e6" + targetPhaseName="oil"/> - - - - - + name="wellControls5" + type="injector" + control="totalVolRate" + referenceElevation="20" + targetBHP="9e7" + targetTotalRate="8e-3" + injectionTemperature="297.15" + injectionStream="{ 0.0, 1.0 }"/> - - - - - + name="wellControls6" + type="injector" + control="totalVolRate" + referenceElevation="20" + targetBHP="9e7" + targetTotalRate="8e-3" + injectionTemperature="297.15" + injectionStream="{ 0.0, 1.0 }"/> - - - - - + name="wellControls7" + type="injector" + control="totalVolRate" + referenceElevation="40" + targetBHP="9e7" + targetTotalRate="8e-3" + injectionTemperature="297.15" + injectionStream="{ 0.0, 1.0 }"/> - - - - - + name="wellControls8" + type="injector" + control="totalVolRate" + referenceElevation="20" + targetBHP="9e7" + targetTotalRate="8e-3" + injectionTemperature="297.15" + injectionStream="{ 0.0, 1.0 }"/> - - - - - + name="wellControls9" + type="injector" + control="totalVolRate" + referenceElevation="20" + targetBHP="9e7" + targetTotalRate="8e-3" + injectionTemperature="297.15" + injectionStream="{ 0.0, 1.0 }"/> - - - - - + name="wellControls10" + type="injector" + control="totalVolRate" + referenceElevation="20" + targetBHP="9e7" + targetTotalRate="8e-3" + injectionTemperature="297.15" + injectionStream="{ 0.0, 1.0 }"/> - - - - - + name="wellControls11" + type="injector" + control="totalVolRate" + referenceElevation="20" + targetBHP="9e7" + targetTotalRate="8e-3" + injectionTemperature="297.15" + injectionStream="{ 0.0, 1.0 }"/> - - - - - + name="wellControls12" + type="injector" + control="totalVolRate" + referenceElevation="20" + targetBHP="9e7" + targetTotalRate="8e-3" + injectionTemperature="297.15" + injectionStream="{ 0.0, 1.0 }"/> + + + maxTime="1.5e7"> - + name="vtk" + timeFrequency="2e6" + target="/Outputs/vtkOutput"/> + - + name="timeHistoryOutput1" + timeFrequency="1.5e7" + target="/Outputs/timeHistoryOutput1"/> + - + name="timeHistoryOutput2" + timeFrequency="1.5e7" + target="/Outputs/timeHistoryOutput2"/> + - + name="timeHistoryOutput3" + timeFrequency="1.5e7" + target="/Outputs/timeHistoryOutput3"/> + - + name="timeHistoryOutput4" + timeFrequency="1.5e7" + target="/Outputs/timeHistoryOutput4"/> + - + name="solverApplications" + maxEventDt="5e5" + target="/Solvers/coupledFlowAndWells"/> + - + name="timeHistoryCollection1" + timeFrequency="1e6" + target="/Tasks/wellRateCollection1"/> + - + name="timeHistoryCollection2" + timeFrequency="1e6" + target="/Tasks/wellRateCollection2"/> + - + name="timeHistoryCollection3" + timeFrequency="1e6" + target="/Tasks/wellRateCollection3"/> + - + name="timeHistoryCollection4" + timeFrequency="1e6" + target="/Tasks/wellRateCollection4"/> + - + name="restarts" + timeFrequency="7.5e6" + targetExactTimestep="0" + target="/Outputs/restartOutput"/> + + + + - + name="fluidTPFA"/> + + + - + name="reservoir" + cellBlocks="{ * }" + materialList="{ fluid, rock, relperm }"/> + - + name="wellRegion1" + materialList="{ fluid }"/> + - + name="wellRegion2" + materialList="{ fluid }"/> + + + - + name="wellRegion3" + materialList="{ fluid }"/> + - + name="wellRegion4" + materialList="{ fluid }"/> + - + name="wellRegion5" + materialList="{ fluid }"/> + - + name="wellRegion6" + materialList="{ fluid }"/> + - + name="wellRegion7" + materialList="{ fluid }"/> + - + name="wellRegion8" + materialList="{ fluid }"/> + - + name="wellRegion9" + materialList="{ fluid }"/> + - + name="wellRegion10" + materialList="{ fluid }"/> + - + name="wellRegion11" + materialList="{ fluid }"/> + - + name="wellRegion12" + materialList="{ fluid }"/> + + - + name="fluid" + phaseNames="{ oil, water }" + surfaceDensities="{ 848.9, 1025.2 }" + componentMolarWeight="{ 114e-3, 18e-3 }" + tableFiles="{ pvdo.txt, pvtw.txt }"/> + - + name="relperm" + phaseNames="{ oil, water }" + phaseMinVolumeFraction="{ 0.1, 0.2 }" + phaseRelPermExponent="{ 4.0, 3.0 }" + phaseRelPermMaxValue="{ 0.8, 0.75 }"/> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> + - + name="nullSolid"/> + - + name="rockPorosity" + defaultReferencePorosity="0.2" + referencePressure="0.0" + compressibility="1.0e-13"/> + - + name="rockPerm" + permeabilityComponents="{ 5.0e-13, 5.0e-13, 1.0e-13 }"/> + + + - + name="initialPressure" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/reservoir/DEFAULT_HEX" + fieldName="pressure" + scale="4e7"/> + - + name="initialComposition_oil" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/reservoir/DEFAULT_HEX" + fieldName="globalCompFraction" + component="0" + scale="0.9"/> + - + name="initialComposition_water" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/reservoir/DEFAULT_HEX" + fieldName="globalCompFraction" + component="1" + scale="0.1"/> + + + - + name="vtkOutput"/> + - + name="timeHistoryOutput1" + sources="{ /Tasks/wellRateCollection1 }" + filename="wellRateHistory1"/> + - + name="timeHistoryOutput2" + sources="{ /Tasks/wellRateCollection2 }" + filename="wellRateHistory2"/> + - + name="timeHistoryOutput3" + sources="{ /Tasks/wellRateCollection3 }" + filename="wellRateHistory3"/> + - + name="timeHistoryOutput4" + sources="{ /Tasks/wellRateCollection4 }" + filename="wellRateHistory4"/> + - + name="restartOutput"/> + + + + - + name="wellRateCollection1" + objectPath="ElementRegions/wellRegion1/wellRegion1UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"/> + - + name="wellRateCollection2" + objectPath="ElementRegions/wellRegion2/wellRegion2UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"/> + - + name="wellRateCollection3" + objectPath="ElementRegions/wellRegion3/wellRegion3UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"/> + - + name="wellRateCollection4" + objectPath="ElementRegions/wellRegion4/wellRegion4UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"/> - \ No newline at end of file + + + diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_iterative.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_iterative.xml index c7a50898ba1..615688bef78 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_iterative.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_iterative.xml @@ -1,450 +1,406 @@ + + + + name="coupledFlowAndWells" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + initialDt="1e4" + targetRegions="{ reservoir, wellRegion1, wellRegion2, wellRegion3, wellRegion4, wellRegion5, wellRegion6, wellRegion7, wellRegion8, wellRegion9, wellRegion10, wellRegion11, wellRegion12 }"> - + newtonTol="1.0e-4" + newtonMaxIter="25" + timeStepDecreaseIterLimit="0.9" + timeStepIncreaseIterLimit="0.6" + timeStepCutFactor="0.1" + maxTimeStepCuts="10" + lineSearchAction="None"/> - + solverType="fgmres" + preconditionerType="mgr" + krylovTol="1e-4" + krylovAdaptiveTol="1" + krylovWeakestTol="1e-2" + logLevel="1"/> + - + name="compositionalMultiphaseFlow" + targetRegions="{ reservoir }" + discretization="fluidTPFA" + temperature="297.15" + maxCompFractionChange="0.3" + logLevel="1" + useMass="1"/> + + name="compositionalMultiphaseWell" + targetRegions="{ wellRegion1, wellRegion2, wellRegion3, wellRegion4, wellRegion5, wellRegion6, wellRegion7, wellRegion8, wellRegion9, wellRegion10, wellRegion11, wellRegion12 }" + maxCompFractionChange="0.5" + logLevel="1" + useMass="1"> - - - - - + name="wellControls1" + type="producer" + control="BHP" + referenceElevation="28" + targetBHP="3.9e7" + targetPhaseRate="1e6" + targetPhaseName="oil"/> - - - - - + name="wellControls2" + type="producer" + control="BHP" + referenceElevation="28" + targetBHP="3.9e7" + targetPhaseRate="1e6" + targetPhaseName="oil"/> + + + - - - - - + name="wellControls3" + type="producer" + control="BHP" + referenceElevation="28" + targetBHP="3.9e7" + targetPhaseRate="1e6" + targetPhaseName="oil"/> - - - - - + name="wellControls4" + type="producer" + control="BHP" + referenceElevation="28" + targetBHP="3.9e7" + targetPhaseRate="1e6" + targetPhaseName="oil"/> - - - - - + name="wellControls5" + type="injector" + control="totalVolRate" + referenceElevation="20" + targetBHP="9e7" + targetTotalRate="8e-3" + injectionTemperature="297.15" + injectionStream="{ 0.0, 1.0 }"/> - - - - - + name="wellControls6" + type="injector" + control="totalVolRate" + referenceElevation="20" + targetBHP="9e7" + targetTotalRate="8e-3" + injectionTemperature="297.15" + injectionStream="{ 0.0, 1.0 }"/> - - - - - + name="wellControls7" + type="injector" + control="totalVolRate" + referenceElevation="40" + targetBHP="9e7" + targetTotalRate="8e-3" + injectionTemperature="297.15" + injectionStream="{ 0.0, 1.0 }"/> - - - - - + name="wellControls8" + type="injector" + control="totalVolRate" + referenceElevation="20" + targetBHP="9e7" + targetTotalRate="8e-3" + injectionTemperature="297.15" + injectionStream="{ 0.0, 1.0 }"/> - - - - - + name="wellControls9" + type="injector" + control="totalVolRate" + referenceElevation="20" + targetBHP="9e7" + targetTotalRate="8e-3" + injectionTemperature="297.15" + injectionStream="{ 0.0, 1.0 }"/> - - - - - + name="wellControls10" + type="injector" + control="totalVolRate" + referenceElevation="20" + targetBHP="9e7" + targetTotalRate="8e-3" + injectionTemperature="297.15" + injectionStream="{ 0.0, 1.0 }"/> - - - - - + name="wellControls11" + type="injector" + control="totalVolRate" + referenceElevation="20" + targetBHP="9e7" + targetTotalRate="8e-3" + injectionTemperature="297.15" + injectionStream="{ 0.0, 1.0 }"/> - - - - - + name="wellControls12" + type="injector" + control="totalVolRate" + referenceElevation="20" + targetBHP="9e7" + targetTotalRate="8e-3" + injectionTemperature="297.15" + injectionStream="{ 0.0, 1.0 }"/> + + + maxTime="1.5e7"> - + name="vtk" + timeFrequency="2e6" + target="/Outputs/vtkOutput"/> + - + name="timeHistoryOutput1" + timeFrequency="1.5e7" + target="/Outputs/timeHistoryOutput1"/> + - + name="timeHistoryOutput2" + timeFrequency="1.5e7" + target="/Outputs/timeHistoryOutput2"/> + - + name="timeHistoryOutput3" + timeFrequency="1.5e7" + target="/Outputs/timeHistoryOutput3"/> + - + name="timeHistoryOutput4" + timeFrequency="1.5e7" + target="/Outputs/timeHistoryOutput4"/> + - + name="solverApplications" + maxEventDt="5e5" + target="/Solvers/coupledFlowAndWells"/> + - + name="timeHistoryCollection1" + timeFrequency="1e6" + target="/Tasks/wellRateCollection1"/> + - + name="timeHistoryCollection2" + timeFrequency="1e6" + target="/Tasks/wellRateCollection2"/> + - + name="timeHistoryCollection3" + timeFrequency="1e6" + target="/Tasks/wellRateCollection3"/> + - + name="timeHistoryCollection4" + timeFrequency="1e6" + target="/Tasks/wellRateCollection4"/> + - + name="restarts" + timeFrequency="7.5e6" + targetExactTimestep="0" + target="/Outputs/restartOutput"/> + + + + - + name="fluidTPFA"/> + + + - + name="reservoir" + cellBlocks="{ * }" + materialList="{ fluid, rock, relperm }"/> + - + name="wellRegion1" + materialList="{ fluid }"/> + - + name="wellRegion2" + materialList="{ fluid }"/> + + + - + name="wellRegion3" + materialList="{ fluid }"/> + - + name="wellRegion4" + materialList="{ fluid }"/> + - + name="wellRegion5" + materialList="{ fluid }"/> + - + name="wellRegion6" + materialList="{ fluid }"/> + - + name="wellRegion7" + materialList="{ fluid }"/> + - + name="wellRegion8" + materialList="{ fluid }"/> + - + name="wellRegion9" + materialList="{ fluid }"/> + - + name="wellRegion10" + materialList="{ fluid }"/> + - + name="wellRegion11" + materialList="{ fluid }"/> + - + name="wellRegion12" + materialList="{ fluid }"/> + + - + name="fluid" + phaseNames="{ oil, water }" + surfaceDensities="{ 848.9, 1025.2 }" + componentMolarWeight="{ 114e-3, 18e-3 }" + tableFiles="{ pvdo.txt, pvtw.txt }"/> + - + name="relperm" + phaseNames="{ oil, water }" + phaseMinVolumeFraction="{ 0.1, 0.2 }" + phaseRelPermExponent="{ 4.0, 3.0 }" + phaseRelPermMaxValue="{ 0.8, 0.75 }"/> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> + - + name="nullSolid"/> + - + name="rockPorosity" + defaultReferencePorosity="0.2" + referencePressure="0.0" + compressibility="1.0e-13"/> + - + name="rockPerm" + permeabilityComponents="{ 1.0e-12, 1.0e-12, 1.0e-12 }"/> + + + - + name="initialPressure" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/reservoir/hexahedra" + fieldName="pressure" + scale="4e7"/> + - + name="initialComposition_oil" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/reservoir/hexahedra" + fieldName="globalCompFraction" + component="0" + scale="0.9"/> + - + name="initialComposition_water" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/reservoir/hexahedra" + fieldName="globalCompFraction" + component="1" + scale="0.1"/> + + + - + name="vtkOutput"/> + - + name="timeHistoryOutput1" + sources="{ /Tasks/wellRateCollection1 }" + filename="wellRateHistory1"/> + - + name="timeHistoryOutput2" + sources="{ /Tasks/wellRateCollection2 }" + filename="wellRateHistory2"/> + - + name="timeHistoryOutput3" + sources="{ /Tasks/wellRateCollection3 }" + filename="wellRateHistory3"/> + - + name="timeHistoryOutput4" + sources="{ /Tasks/wellRateCollection4 }" + filename="wellRateHistory4"/> + - + name="restartOutput"/> + + + + - + name="wellRateCollection1" + objectPath="ElementRegions/wellRegion1/wellRegion1UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"/> + - + name="wellRateCollection2" + objectPath="ElementRegions/wellRegion2/wellRegion2UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"/> + - + name="wellRateCollection3" + objectPath="ElementRegions/wellRegion3/wellRegion3UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"/> + - + name="wellRateCollection4" + objectPath="ElementRegions/wellRegion4/wellRegion4UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"/> - \ No newline at end of file + + + diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d.xml index 1df2ffc30de..7ebac080cbc 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d.xml @@ -1,313 +1,304 @@ + + + + name="reservoirSystem" + wellSolverName="compositionalMultiphaseWell" + flowSolverName="compositionalMultiphaseFlow" + logLevel="1" + initialDt="86400" + targetRegions="{ region, wellRegion1, wellRegion2 }"> - - - + maxTimeStepCuts="5" + newtonTol="1e-8" + newtonMaxIter="20"/> + + - + name="compositionalMultiphaseFlow" + logLevel="1" + discretization="fluidTPFA" + targetRelativePressureChangeInTimeStep="1" + targetPhaseVolFractionChangeInTimeStep="1" + targetRegions="{ region }" + temperature="297.15" + useMass="1"/> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{ wellRegion1, wellRegion2 }" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1" + useMass="1"> - - - - - + name="wellControls1" + type="producer" + control="BHP" + referenceElevation="9" + targetBHP="1.2e+7" + targetPhaseRate="5e-2" + targetPhaseName="oil"/> - - - - - + name="wellControls2" + type="injector" + control="BHP" + referenceElevation="9" + targetBHP="2e+7" + targetTotalRate="5e-2" + injectionTemperature="297.15" + injectionStream="{ 0.000, 0.000, 1. }"/> + + + name="mesh" + elementTypes="{ C3D8 }" + xCoords="{ 0, 200 }" + yCoords="{ 0, 200 }" + zCoords="{ 0, 10 }" + nx="{ 4 }" + ny="{ 4 }" + nz="{ 2 }" + cellBlockNames="{ cb }"> + + name="wellProducer" + wellRegionName="wellRegion1" + wellControlsName="wellControls1" + polylineNodeCoords="{ { 5.0, 5.0, 2.0 }, + { 5.0, 5.0, 0.0 } }" + polylineSegmentConn="{ { 0, 1 } }" + radius="0.1" + numElementsPerSegment="1"> - + name="producerPerf1" + distanceFromHead="1.00"/> + name="wellInjector" + wellRegionName="wellRegion2" + wellControlsName="wellControls2" + polylineNodeCoords="{ { 195.0, 195.0, 2.0 }, + { 195.0, 195.0, 0.0 } }" + polylineSegmentConn="{ { 0, 1 } }" + radius="0.1" + numElementsPerSegment="1"> - + name="injectorPerf1" + distanceFromHead="1.00"/> - + - + name="outputs" + timeFrequency="3153600" + targetExactTimestep="1" + target="/Outputs/vtkOutput"/> + - + name="timeHistoryOutput" + timeFrequency="3153600" + targetExactTimestep="1" + target="/Outputs/timeHistoryOutput"/> + - + name="restarts" + timeFrequency="1576800" + targetExactTimestep="1" + target="/Outputs/restartOutput"/> + - + name="solverApplications" + maxEventDt="315360" + target="/Solvers/reservoirSystem"/> + - + name="statistics" + timeFrequency="3153600" + target="/Tasks/compositionalMultiphaseFlowStatistics"/> + - + name="timeHistoryCollection" + timeFrequency="315360" + targetExactTimestep="1" + target="/Tasks/wellRateCollection"/> + + - + name="fluidTPFA"/> + - + name="region" + cellBlocks="{ * }" + materialList="{ fluid, rock, relperm, cappres }"/> - + name="wellRegion1" + materialList="{ fluid }"/> - + name="wellRegion2" + materialList="{ fluid }"/> + - + name="fluid" + phaseNames="{ oil, gas, water }" + surfaceDensities="{ 800.907131537, 0.856234902739, 1020.3440 }" + componentMolarWeight="{ 120e-3, 25e-3, 18e-3 }" + tableFiles="{ pvto_bo.txt, pvtg_norv_bo.txt, pvtw_bo.txt }"/> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> + - + name="nullSolid"/> + - + name="rockPorosity" + defaultReferencePorosity="0.2" + referencePressure="4.1369e7" + compressibility="1.0e-9"/> + - + name="relperm" + phaseNames="{ oil, gas, water }" + wettingIntermediateRelPermTableNames="{ waterRelPermTable, oilRelPermTableForOW }" + nonWettingIntermediateRelPermTableNames="{ gasRelPermTable, oilRelPermTableForOG }"/> + - + name="cappres" + phaseNames="{ oil, gas, water }" + wettingIntermediateCapPressureTableName="waterCapPresTable" + nonWettingIntermediateCapPressureTableName="gasCapPresTable"/> + - + name="rockPerm" + permeabilityComponents="{ 1.0e-14, 1.0e-14, 1.0e-14 }"/> + + + - + name="initialPressure" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="pressure" + scale="1.5e+7"/> - + name="initialComposition_oil" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="0" + scale="0.79999"/> - + name="initialComposition_gas" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="1" + scale="0.2"/> - + name="initialComposition_water" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="2" + scale="0.00001"/> + + - + name="waterRelPermTable" + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, + 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, + 0.2500, 0.3025, 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000 }"/> - + name="oilRelPermTableForOW" + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, + 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, + 0.2500, 0.3025, 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000 }"/> - + name="gasRelPermTable" + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, + 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, + 0.2500, 0.3025, 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000 }"/> - + name="oilRelPermTableForOG" + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, + 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, + 0.2500, 0.3025, 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000 }"/> + - + name="waterCapPresTable" + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, + 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 10000, 9025, 8100, 7225, 6400, 5625, 4900, 4225, 3600, 3025, + 2500, 2025, 1600, 1225, 900, 625, 400, 225, 100, 25, 0 }"/> - + name="gasCapPresTable" + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, + 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 50, 200, 450, 800, 1250, 1800, 2450, 3200, 4050, 5000, 6050, + 7200, 8450, 9800, 11250, 12800, 14450, 16200, 18050, 20000 }"/> + + - + name="compositionalMultiphaseFlowStatistics" + flowSolverName="compositionalMultiphaseFlow" + logLevel="1" + computeCFLNumbers="1" + computeRegionStatistics="1"/> + - + name="wellRateCollection" + objectPath="ElementRegions/wellRegion1/wellRegion1UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"/> + - + name="vtkOutput"/> + - + name="timeHistoryOutput" + sources="{ /Tasks/wellRateCollection }" + filename="wellRateHistory"/> + - + name="restartOutput"/> - \ No newline at end of file + + diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml index 1b3b56c03cd..ce669961545 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml @@ -1,314 +1,304 @@ + + + + name="reservoirSystem" + wellSolverName="compositionalMultiphaseWell" + flowSolverName="compositionalMultiphaseFlow" + logLevel="1" + initialDt="86400" + targetRegions="{ region, wellRegion1, wellRegion2 }"> - - - + maxTimeStepCuts="5" + newtonTol="1e-8" + newtonMaxIter="20"/> + + - + name="compositionalMultiphaseFlow" + logLevel="1" + discretization="fluidTPFA" + targetRelativePressureChangeInTimeStep="1" + targetPhaseVolFractionChangeInTimeStep="1" + targetRegions="{ region }" + temperature="297.15" + useMass="1"/> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{ wellRegion1, wellRegion2 }" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1" + useMass="1"> - - - - - + name="wellControls1" + type="producer" + control="BHP" + referenceElevation="9" + targetBHP="1.2e+7" + targetPhaseRate="5e-2" + targetPhaseName="oil"/> - - - - - + name="wellControls2" + type="injector" + control="BHP" + referenceElevation="9" + targetBHP="2e+7" + targetTotalRate="5e-2" + injectionTemperature="297.15" + injectionStream="{ 0.000, 0.000, 1. }"/> + + - - - - - - - - + name="mesh" + elementTypes="{ C3D8 }" + xCoords="{ 0, 200 }" + yCoords="{ 0, 200 }" + zCoords="{ 0, 10 }" + nx="{ 4 }" + ny="{ 4 }" + nz="{ 2 }" + cellBlockNames="{ cb }"> + + + + + + - + - + name="outputs" + timeFrequency="3153600" + targetExactTimestep="1" + target="/Outputs/vtkOutput"/> + - + name="timeHistoryOutput" + timeFrequency="3153600" + targetExactTimestep="1" + target="/Outputs/timeHistoryOutput"/> + - + name="restarts" + timeFrequency="1576800" + targetExactTimestep="1" + target="/Outputs/restartOutput"/> + - + name="solverApplications" + maxEventDt="315360" + target="/Solvers/reservoirSystem"/> + - + name="statistics" + timeFrequency="3153600" + target="/Tasks/compositionalMultiphaseFlowStatistics"/> + - + name="timeHistoryCollection" + timeFrequency="315360" + targetExactTimestep="1" + target="/Tasks/wellRateCollection"/> + + - + name="fluidTPFA"/> + - + name="region" + cellBlocks="{ * }" + materialList="{ fluid, rock, relperm, cappres }"/> - + name="wellRegion1" + materialList="{ fluid }"/> - + name="wellRegion2" + materialList="{ fluid }"/> + - + name="fluid" + phaseNames="{ oil, gas, water }" + surfaceDensities="{ 800.907131537, 0.856234902739, 1020.3440 }" + componentMolarWeight="{ 120e-3, 25e-3, 18e-3 }" + tableFiles="{ pvto_bo.txt, pvtg_norv_bo.txt, pvtw_bo.txt }"/> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> + - + name="nullSolid"/> + - + name="rockPorosity" + defaultReferencePorosity="0.2" + referencePressure="4.1369e7" + compressibility="1.0e-9"/> + - + name="relperm" + phaseNames="{ oil, gas, water }" + wettingIntermediateRelPermTableNames="{ waterRelPermTable, oilRelPermTableForOW }" + nonWettingIntermediateRelPermTableNames="{ gasRelPermTable, oilRelPermTableForOG }" + threePhaseInterpolator="STONEII"/> + - + name="cappres" + phaseNames="{ oil, gas, water }" + wettingIntermediateCapPressureTableName="waterCapPresTable" + nonWettingIntermediateCapPressureTableName="gasCapPresTable"/> + - + name="rockPerm" + permeabilityComponents="{ 1.0e-14, 1.0e-14, 1.0e-14 }"/> + + + - + name="initialPressure" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="pressure" + scale="1.5e+7"/> - + name="initialComposition_oil" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="0" + scale="0.79999"/> - + name="initialComposition_gas" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="1" + scale="0.2"/> - + name="initialComposition_water" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="2" + scale="0.00001"/> + + - + name="waterRelPermTable" + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, + 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, + 0.2500, 0.3025, 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000 }"/> - + name="oilRelPermTableForOW" + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, + 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, + 0.2500, 0.3025, 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000 }"/> - + name="gasRelPermTable" + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, + 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, + 0.2500, 0.3025, 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000 }"/> - + name="oilRelPermTableForOG" + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, + 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, + 0.2500, 0.3025, 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000 }"/> + - + name="waterCapPresTable" + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, + 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 10000, 9025, 8100, 7225, 6400, 5625, 4900, 4225, 3600, 3025, + 2500, 2025, 1600, 1225, 900, 625, 400, 225, 100, 25, 0 }"/> - + name="gasCapPresTable" + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, + 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 50, 200, 450, 800, 1250, 1800, 2450, 3200, 4050, 5000, 6050, + 7200, 8450, 9800, 11250, 12800, 14450, 16200, 18050, 20000 }"/> + + - + name="compositionalMultiphaseFlowStatistics" + flowSolverName="compositionalMultiphaseFlow" + logLevel="1" + computeCFLNumbers="1" + computeRegionStatistics="1"/> + - + name="wellRateCollection" + objectPath="ElementRegions/wellRegion1/wellRegion1UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"/> + - + name="vtkOutput"/> + - + name="timeHistoryOutput" + sources="{ /Tasks/wellRateCollection }" + filename="wellRateHistory"/> + - + name="restartOutput"/> - \ No newline at end of file + + diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml index e2aa359a44e..323b9a144c6 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml @@ -1,265 +1,258 @@ + + + + name="reservoirSystem" + wellSolverName="compositionalMultiphaseWell" + flowSolverName="compositionalMultiphaseFlow" + logLevel="1" + initialDt="86400" + targetRegions="{ region, wellRegion1, wellRegion2 }"> - - - + maxTimeStepCuts="5" + newtonTol="1e-8" + newtonMaxIter="20"/> + + - + name="compositionalMultiphaseFlow" + logLevel="1" + discretization="fluidHM" + targetRelativePressureChangeInTimeStep="1" + targetPhaseVolFractionChangeInTimeStep="1" + targetRegions="{ region }" + temperature="297.15" + useMass="1"/> + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{ wellRegion1, wellRegion2 }" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1" + useMass="1"> - - - - - + name="wellControls1" + type="producer" + control="BHP" + referenceElevation="9" + targetBHP="1.2e+7" + targetPhaseRate="5e-2" + targetPhaseName="oil"/> - - - - - + name="wellControls2" + type="injector" + control="BHP" + referenceElevation="9" + targetBHP="2e+7" + targetTotalRate="5e-2" + injectionTemperature="297.15" + injectionStream="{ 0.000, 0.000, 1. }"/> + + + name="mesh" + elementTypes="{ C3D8 }" + xCoords="{ 0, 200 }" + yCoords="{ 0, 200 }" + zCoords="{ 0, 10 }" + nx="{ 4 }" + ny="{ 4 }" + nz="{ 2 }" + cellBlockNames="{ cb }"> + + name="wellProducer" + wellRegionName="wellRegion1" + wellControlsName="wellControls1" + polylineNodeCoords="{ { 5.0, 5.0, 2.0 }, + { 5.0, 5.0, 0.0 } }" + polylineSegmentConn="{ { 0, 1 } }" + radius="0.1" + numElementsPerSegment="1"> - + name="producerPerf1" + distanceFromHead="1.00"/> + name="wellInjector" + wellRegionName="wellRegion2" + wellControlsName="wellControls2" + polylineNodeCoords="{ { 195.0, 195.0, 2.0 }, + { 195.0, 195.0, 0.0 } }" + polylineSegmentConn="{ { 0, 1 } }" + radius="0.1" + numElementsPerSegment="1"> - + name="injectorPerf1" + distanceFromHead="1.00"/> - + + + - + name="outputs" + timeFrequency="3153600" + targetExactTimestep="1" + target="/Outputs/vtkOutput"/> + - + name="timeHistoryOutput" + timeFrequency="3153600" + targetExactTimestep="1" + target="/Outputs/timeHistoryOutput"/> + + + - + name="solverApplications" + maxEventDt="315360" + target="/Solvers/reservoirSystem"/> + - + name="statistics" + timeFrequency="3153600" + target="/Tasks/compositionalMultiphaseFlowStatistics"/> + - - - + name="timeHistoryCollection" + timeFrequency="315360" + targetExactTimestep="1" + target="/Tasks/wellRateCollection"/> + + - + name="fluidHM" + innerProductType="TPFA"/> + - + name="region" + cellBlocks="{ * }" + materialList="{ fluid, rock, relperm }"/> - + name="wellRegion1" + materialList="{ fluid }"/> - + name="wellRegion2" + materialList="{ fluid }"/> + - + name="fluid" + phaseNames="{ oil, gas, water }" + surfaceDensities="{ 800.907131537, 0.856234902739, 1020.3440 }" + componentMolarWeight="{ 120e-3, 25e-3, 18e-3 }" + tableFiles="{ pvto_bo.txt, pvtg_norv_bo.txt, pvtw_bo.txt }"/> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> + - + name="nullSolid"/> + - + name="rockPorosity" + defaultReferencePorosity="0.2" + referencePressure="4.1369e7" + compressibility="1.0e-9"/> + - + name="relperm" + phaseNames="{ oil, gas, water }" + phaseMinVolumeFraction="{ 0.0, 0.0, 0.0}" + phaseRelPermExponent="{ 2.0, 2.0, 2.0}" + phaseRelPermMaxValue="{ 1.0, 1.0, 1.0 }"/> + - + name="rockPerm" + permeabilityComponents="{ 1.0e-14, 1.0e-14, 1.0e-14 }"/> + + + - + name="initialPressure" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="pressure" + scale="1.5e+7"/> - + name="initialComposition_oil" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="0" + scale="0.89999"/> - + name="initialComposition_gas" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="1" + scale="0.1"/> - + name="initialComposition_water" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="2" + scale="0.00001"/> - + + - + name="compositionalMultiphaseFlowStatistics" + flowSolverName="compositionalMultiphaseFlow" + logLevel="1" + computeCFLNumbers="0" + computeRegionStatistics="1"/> + - + name="wellRateCollection" + objectPath="ElementRegions/wellRegion1/wellRegion1UniqueSubRegion" + fieldName="wellElementMixtureConnectionRate"/> + - + name="vtkOutput"/> + - + name="timeHistoryOutput" + sources="{ /Tasks/wellRateCollection }" + filename="wellRateHistory"/> + - + name="restartOutput"/> + - \ No newline at end of file + + diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml index 04ae87437ad..ea41c8adf9c 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml @@ -1,267 +1,260 @@ + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_1d.xml b/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_1d.xml index a734fa1ca50..bea2c48815d 100644 --- a/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_1d.xml +++ b/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_1d.xml @@ -1,234 +1,232 @@ + + + name="reservoirSystem" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{ Region1, wellRegion1, wellRegion2 }"> - + newtonTol="1.0e-8" + lineSearchAction="None" + newtonMaxIter="40"/> - + directParallel="0"/> + - + name="compositionalMultiphaseFlow" + logLevel="1" + discretization="fluidTPFA" + targetRegions="{ Region1 }" + temperature="297.15"/> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{ wellRegion1, wellRegion2 }"> - - - - - + name="wellControls1" + type="producer" + control="BHP" + referenceElevation="2" + targetBHP="4e6" + targetPhaseRate="1e-3" + targetPhaseName="oil"/> - - - - - + name="wellControls2" + type="injector" + control="totalVolRate" + referenceElevation="2" + targetBHP="1e8" + targetTotalRate="1e-7" + injectionTemperature="297.15" + injectionStream="{ 0.1, 0.1, 0.1, 0.7 }"/> + + name="mesh1" + elementTypes="{ C3D8 }" + xCoords="{ 0, 5 }" + yCoords="{ 0, 1 }" + zCoords="{ 0, 1 }" + nx="{ 5 }" + ny="{ 1 }" + nz="{ 1 }" + cellBlockNames="{ cb1 }"> + + name="well_producer1" + wellRegionName="wellRegion1" + wellControlsName="wellControls1" + polylineNodeCoords="{ { 4.5, 0, 2 }, + { 4.5, 0, 0.5 } }" + polylineSegmentConn="{ { 0, 1 } }" + radius="0.1" + numElementsPerSegment="2"> - + name="producer1_perf1" + distanceFromHead="1.45"/> + + name="well_injector1" + wellRegionName="wellRegion2" + wellControlsName="wellControls2" + polylineNodeCoords="{ { 0.5, 0, 2 }, + { 0.5, 0, 0.5 } }" + polylineSegmentConn="{ { 0, 1 } }" + radius="0.1" + numElementsPerSegment="3"> - + name="injector1_perf1" + distanceFromHead="1.45"/> + + maxTime="2.5e4"> - + name="solverApplications" + forceDt="2.5e3" + target="/Solvers/reservoirSystem"/> + - + name="outputs" + timeFrequency="2.5e3" + target="/Outputs/vtkOutput"/> + - + name="restarts" + timeFrequency="1.25e4" + targetExactTimestep="0" + target="/Outputs/restartOutput"/> + - + name="fluidTPFA" + /> + - + name="Region1" + cellBlocks="{ * }" + materialList="{ fluid1, rock, relperm }"/> + - + name="wellRegion1" + materialList="{ fluid1 }"/> + - + name="wellRegion2" + materialList="{ fluid1 }"/> + - + name="fluid1" + phaseNames="{ oil, gas }" + equationsOfState="{ PR, PR }" + componentNames="{ N2, C10, C20, H2O }" + componentCriticalPressure="{ 34e5, 25.3e5, 14.6e5, 220.5e5 }" + componentCriticalTemperature="{ 126.2, 622.0, 782.0, 647.0 }" + componentAcentricFactor="{ 0.04, 0.443, 0.816, 0.344 }" + componentMolarWeight="{ 28e-3, 134e-3, 275e-3, 18e-3 }" + componentVolumeShift="{ 0, 0, 0, 0 }" + componentBinaryCoeff="{ { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 } }"/> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> + - + name="nullSolid"/> + - + name="rockPorosity" + defaultReferencePorosity="0.05" + referencePressure="0.0" + compressibility="1.0e-9"/> + - + name="relperm" + phaseNames="{ oil, gas }" + phaseMinVolumeFraction="{ 0.1, 0.15 }" + phaseRelPermExponent="{ 2.0, 2.0 }" + phaseRelPermMaxValue="{ 0.8, 0.9 }"/> + - + name="rockPerm" + permeabilityComponents="{ 2.0e-16, 2.0e-16, 2.0e-16 }"/> + + - + name="initialPressure" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Region1/cb1" + fieldName="pressure" + scale="5e6"/> + + - + name="initialComposition_N2" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="0" + scale="0.099"/> + - + name="initialComposition_C10" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="1" + scale="0.3"/> + - + name="initialComposition_C20" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="2" + scale="0.6"/> + - + name="initialComposition_H20" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="3" + scale="0.001"/> + - + name="vtkOutput"/> + - + name="restartOutput"/> - \ No newline at end of file + diff --git a/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_2d.xml b/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_2d.xml index 1deb55d537f..81e2212e304 100644 --- a/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_2d.xml +++ b/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_2d.xml @@ -1,285 +1,280 @@ + + + name="reservoirSystem" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{ Region1, wellRegion1, wellRegion2, wellRegion3 }"> - + newtonTol="1.0e-8" + lineSearchAction="None" + newtonMaxIter="40"/> - + directParallel="0"/> + - + name="compositionalMultiphaseFlow" + logLevel="1" + discretization="fluidTPFA" + targetRegions="{ Region1 }" + temperature="297.15"/> + + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{ wellRegion1, wellRegion2, wellRegion3 }"> - - - - - + name="wellControls1" + type="producer" + control="BHP" + referenceElevation="0.5" + targetBHP="4e6" + targetPhaseRate="1e-3" + targetPhaseName="oil"/> - - - - - + name="wellControls2" + type="producer" + control="phaseVolRate" + referenceElevation="0.5" + targetBHP="2e6" + targetPhaseRate="2.5e-7" + targetPhaseName="oil"/> - - - - - + name="wellControls3" + type="injector" + control="totalVolRate" + referenceElevation="0.5" + targetBHP="4e7" + targetTotalRate="5e-7" + injectionTemperature="297.15" + injectionStream="{ 0.1, 0.1, 0.1, 0.7 }"/> + + + + name="mesh1" + elementTypes="{ C3D8 }" + xCoords="{ 0, 15 }" + yCoords="{ 0, 15 }" + zCoords="{ 0, 1 }" + nx="{ 20 }" + ny="{ 20 }" + nz="{ 1 }" + cellBlockNames="{ cb1 }"> + + name="well_producer1" + wellRegionName="wellRegion1" + wellControlsName="wellControls1" + polylineNodeCoords="{ { 0.5, 0.5, 0.5 }, + { 7.5, 0.5, 0.35 }, + { 14.5, 0.5, 0.2 } }" + polylineSegmentConn="{ { 0, 1 }, + { 1, 2 } }" + radius="0.1" + numElementsPerSegment="20"> - + name="producer1_perf1" + distanceFromHead="14"/> - + name="producer1_perf2" + distanceFromHead="11"/> - + name="producer1_perf3" + distanceFromHead="8"/> + + name="well_producer2" + wellRegionName="wellRegion2" + wellControlsName="wellControls2" + polylineNodeCoords="{ { 14.5, 14.5, 0.5 }, + { 7.5, 14.5, 0.35 }, + { 0.5, 14.5, 0.2 } }" + polylineSegmentConn="{ { 0, 1 }, + { 1, 2 } }" + radius="0.1" + numElementsPerSegment="17"> - + name="producer2_perf1" + distanceFromHead="14."/> - + name="producer2_perf2" + distanceFromHead="10"/> - + name="producer2_perf3" + distanceFromHead="6"/> + + name="well_injector1" + wellRegionName="wellRegion3" + wellControlsName="wellControls3" + polylineNodeCoords="{ { 0.5, 0.5, 0.5 }, + { 14.5, 14.5, 0.2 } }" + polylineSegmentConn="{ { 0, 1 } }" + radius="0.1" + numElementsPerSegment="30"> - + name="injector1_perf1" + distanceFromHead="19.5"/> - + name="injector1_perf2" + distanceFromHead="10.45"/> + + maxTime="7e3"> - + name="solverApplications" + forceDt="1e3" + target="/Solvers/reservoirSystem"/> + - + name="outputs" + timeFrequency="1e3" + target="/Outputs/siloOutput"/> + - + name="restarts" + timeFrequency="3e3" + targetExactTimestep="0" + target="/Outputs/restartOutput"/> + - + name="fluidTPFA" + /> + - + name="Region1" + cellBlocks="{ * }" + materialList="{ fluid1, rock, relperm }"/> + - + name="wellRegion1" + materialList="{ fluid1 }"/> + - + name="wellRegion2" + materialList="{ fluid1 }"/> + - + name="wellRegion3" + materialList="{ fluid1 }"/> + - + name="fluid1" + phaseNames="{ oil, gas }" + equationsOfState="{ PR, PR }" + componentNames="{ N2, C10, C20, H2O }" + componentCriticalPressure="{ 34e5, 25.3e5, 14.6e5, 220.5e5 }" + componentCriticalTemperature="{ 126.2, 622.0, 782.0, 647.0 }" + componentAcentricFactor="{ 0.04, 0.443, 0.816, 0.344 }" + componentMolarWeight="{ 28e-3, 134e-3, 275e-3, 18e-3 }" + componentVolumeShift="{ 0, 0, 0, 0 }" + componentBinaryCoeff="{ { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 } }"/> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> + - + name="nullSolid"/> + - + name="rockPorosity" + defaultReferencePorosity="0.05" + referencePressure="0.0" + compressibility="1.0e-9"/> + - + name="relperm" + phaseNames="{ oil, gas }" + phaseMinVolumeFraction="{ 0.1, 0.15 }" + phaseRelPermExponent="{ 2.0, 2.0 }" + phaseRelPermMaxValue="{ 0.8, 0.9 }"/> + - + name="rockPerm" + permeabilityComponents="{ 2.0e-16, 2.0e-16, 2.0e-16 }"/> + + - + name="initialPressure" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Region1/cb1" + fieldName="pressure" + scale="5e6"/> + + - + name="initialComposition_N2" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="0" + scale="0.099"/> + - + name="initialComposition_C10" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="1" + scale="0.3"/> + - + name="initialComposition_C20" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="2" + scale="0.6"/> + - + name="initialComposition_H20" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="3" + scale="0.001"/> + - + name="siloOutput"/> + - + name="restartOutput"/> - \ No newline at end of file + diff --git a/inputFiles/compositionalMultiphaseWell/dead_oil_wells_2d.xml b/inputFiles/compositionalMultiphaseWell/dead_oil_wells_2d.xml index ba23381034b..4e97569f8f9 100644 --- a/inputFiles/compositionalMultiphaseWell/dead_oil_wells_2d.xml +++ b/inputFiles/compositionalMultiphaseWell/dead_oil_wells_2d.xml @@ -1,311 +1,301 @@ + + + name="reservoirSystem" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{ Region1, wellRegion1, wellRegion2, wellRegion3 }"> - + newtonTol="1e-8" + newtonMaxIter="40"/> - + directParallel="0"/> + - + name="compositionalMultiphaseFlow" + logLevel="1" + targetRelativePressureChangeInTimeStep="1" + targetPhaseVolFractionChangeInTimeStep="1" + discretization="fluidTPFA" + targetRegions="{ Region1 }" + temperature="297.15"/> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{ wellRegion1, wellRegion2, wellRegion3 }" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1"> - - - - - + name="wellControls1" + type="producer" + control="BHP" + referenceElevation="0.5" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="297.15" + targetBHPTableName="BHPTable" + targetPhaseRate="1e-3" + targetPhaseName="oil"/> - - - - - + name="wellControls2" + type="producer" + control="phaseVolRate" + referenceElevation="0.5" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="297.15" + targetBHP="3e6" + targetPhaseRate="1e-7" + targetPhaseName="oil"/> - - - - - + name="wellControls3" + type="injector" + control="totalVolRate" + referenceElevation="0.5" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="297.15" + targetBHP="4.5e7" + targetTotalRate="1e-5" + injectionTemperature="297.15" + injectionStream="{ 0.0, 0.0, 1.0 }"/> + + name="mesh1" + elementTypes="{ C3D8 }" + xCoords="{ 0, 15 }" + yCoords="{ 0, 15 }" + zCoords="{ 0, 1 }" + nx="{ 20 }" + ny="{ 20 }" + nz="{ 1 }" + cellBlockNames="{ cb1 }"> + + name="well_producer1" + wellRegionName="wellRegion1" + wellControlsName="wellControls1" + polylineNodeCoords="{ { 0.5, 0.5, 0.5 }, + { 7.5, 0.5, 0.35 }, + { 14.5, 0.5, 0.2 } }" + polylineSegmentConn="{ { 0, 1 }, + { 1, 2 } }" + radius="0.1" + numElementsPerSegment="20"> - + name="producer1_perf1" + distanceFromHead="14"/> - + name="producer1_perf2" + distanceFromHead="11"/> - + name="producer1_perf3" + distanceFromHead="8"/> + + name="well_producer2" + wellRegionName="wellRegion2" + wellControlsName="wellControls2" + polylineNodeCoords="{ { 14.5, 14.5, 0.5 }, + { 7.5, 14.5, 0.35 }, + { 0.5, 14.5, 0.2 } }" + polylineSegmentConn="{ { 0, 1 }, + { 1, 2 } }" + radius="0.1" + numElementsPerSegment="17"> - + name="producer2_perf1" + distanceFromHead="14."/> - + name="producer2_perf2" + distanceFromHead="10"/> - + name="producer2_perf3" + distanceFromHead="6"/> + + name="well_injector1" + wellRegionName="wellRegion3" + wellControlsName="wellControls3" + polylineNodeCoords="{ { 0.5, 0.5, 0.5 }, + { 14.5, 14.5, 0.2 } }" + polylineSegmentConn="{ { 0, 1 } }" + radius="0.1" + numElementsPerSegment="30"> - + name="injector1_perf1" + distanceFromHead="19.5"/> - + name="injector1_perf2" + distanceFromHead="10.45"/> + + maxTime="5e5"> - + name="solverApplications" + forceDt="5e3" + target="/Solvers/reservoirSystem"/> + - + name="outputs" + timeFrequency="5e4" + target="/Outputs/vtkOutput"/> + - + name="restarts" + timeFrequency="2.5e5" + targetExactTimestep="0" + target="/Outputs/restartOutput"/> + - + name="fluidTPFA" + /> + - + name="Region1" + cellBlocks="{ * }" + materialList="{ fluid1, rock, relperm }"/> + - + name="wellRegion1" + materialList="{ fluid1 }"/> + - + name="wellRegion2" + materialList="{ fluid1 }"/> + - + name="wellRegion3" + materialList="{ fluid1 }"/> + - + name="fluid1" + phaseNames="{ oil, gas, water }" + surfaceDensities="{ 800.0, 0.9907, 1022.0 }" + componentMolarWeight="{ 114e-3, 16e-3, 18e-3 }" + tableFiles="{ pvdo.txt, pvdg.txt, pvtw.txt }"/> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> + - + name="nullSolid"/> + - + name="rockPorosity" + defaultReferencePorosity="0.05" + referencePressure="0.0" + compressibility="1.0e-9"/> + - + name="relperm" + phaseNames="{ oil, gas, water }" + wettingIntermediateRelPermTableNames="{ waterRelPermTable, oilRelPermTableForOW }" + nonWettingIntermediateRelPermTableNames="{ gasRelPermTable, oilRelPermTableForOG }"/> + - + name="rockPerm" + permeabilityComponents="{ 2.0e-16, 2.0e-16, 2.0e-16 }"/> + + - + name="initialPressure" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Region1/cb1" + fieldName="pressure" + scale="5e6"/> + + - + name="initialComposition_oil" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="0" + scale="0.6"/> + - + name="initialComposition_gas" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="1" + scale="0.399"/> + - + name="initialComposition_water" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="2" + scale="0.001"/> + + - + name="BHPTable" + inputVarNames="{ time }" + coordinates="{ 0, 10e10 }" + values="{ 4e6, 4e6 }" + interpolation="lower"/> + - + name="waterRelPermTable" + coordinateFiles="{ satw.txt }" + voxelFile="krw.txt"/> + - + name="oilRelPermTableForOW" + coordinateFiles="{ sato.txt }" + voxelFile="krow.txt"/> + - + name="gasRelPermTable" + coordinateFiles="{ satg.txt }" + voxelFile="krg.txt"/> + - + name="oilRelPermTableForOG" + coordinateFiles="{ sato.txt }" + voxelFile="krog.txt"/> + - + name="vtkOutput"/> + - + name="restartOutput"/> - \ No newline at end of file + diff --git a/inputFiles/compositionalMultiphaseWell/dead_oil_wells_hybrid_2d.xml b/inputFiles/compositionalMultiphaseWell/dead_oil_wells_hybrid_2d.xml index f88b830bb37..8434ee6c709 100644 --- a/inputFiles/compositionalMultiphaseWell/dead_oil_wells_hybrid_2d.xml +++ b/inputFiles/compositionalMultiphaseWell/dead_oil_wells_hybrid_2d.xml @@ -1,291 +1,279 @@ + + + name="reservoirSystem" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{ Region1, wellRegion1, wellRegion2, wellRegion3 }"> - + newtonMaxIter="40"/> - + directParallel="0"/> + - + name="compositionalMultiphaseFlow" + logLevel="1" + targetRelativePressureChangeInTimeStep="1" + targetPhaseVolFractionChangeInTimeStep="1" + discretization="fluidHM" + targetRegions="{ Region1 }" + temperature="297.15"/> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{ wellRegion1, wellRegion2, wellRegion3 }" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1"> - - - - - + name="wellControls1" + type="producer" + control="BHP" + referenceElevation="0.5" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="297.15" + targetBHP="4e6" + targetPhaseRate="1e-3" + targetPhaseName="oil"/> - - - - - + name="wellControls2" + type="producer" + control="BHP" + referenceElevation="0.5" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="297.15" + targetBHP="3e6" + targetPhaseRate="1e-7" + targetPhaseName="oil"/> - - - - - + name="wellControls3" + type="injector" + control="totalVolRate" + referenceElevation="0.5" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="297.15" + targetBHP="4.5e7" + targetTotalRate="1e-5" + injectionTemperature="297.15" + injectionStream="{ 0.0, 0.0, 1.0 }"/> + + name="mesh1" + elementTypes="{ C3D8 }" + xCoords="{ 0, 15 }" + yCoords="{ 0, 15 }" + zCoords="{ 0, 1 }" + nx="{ 20 }" + ny="{ 20 }" + nz="{ 1 }" + cellBlockNames="{ cb1 }"> + + name="well_producer1" + wellRegionName="wellRegion1" + wellControlsName="wellControls1" + polylineNodeCoords="{ { 0.5, 0.5, 0.5 }, + { 7.5, 0.5, 0.35 }, + { 14.5, 0.5, 0.2 } }" + polylineSegmentConn="{ { 0, 1 }, + { 1, 2 } }" + radius="0.1" + numElementsPerSegment="20"> - + name="producer1_perf1" + distanceFromHead="14"/> - + name="producer1_perf2" + distanceFromHead="11"/> - + name="producer1_perf3" + distanceFromHead="8"/> + + name="well_producer2" + wellRegionName="wellRegion2" + wellControlsName="wellControls2" + polylineNodeCoords="{ { 14.5, 14.5, 0.5 }, + { 7.5, 14.5, 0.35 }, + { 0.5, 14.5, 0.2 } }" + polylineSegmentConn="{ { 0, 1 }, + { 1, 2 } }" + radius="0.1" + numElementsPerSegment="17"> - + name="producer2_perf1" + distanceFromHead="14."/> - + name="producer2_perf2" + distanceFromHead="10"/> - + name="producer2_perf3" + distanceFromHead="6"/> + + name="well_injector1" + wellRegionName="wellRegion3" + wellControlsName="wellControls3" + polylineNodeCoords="{ { 0.5, 0.5, 0.5 }, + { 14.5, 14.5, 0.2 } }" + polylineSegmentConn="{ { 0, 1 } }" + radius="0.1" + numElementsPerSegment="30"> - + name="injector1_perf1" + distanceFromHead="19.5"/> - + name="injector1_perf2" + distanceFromHead="10.45"/> + + maxTime="5e5"> - + name="solverApplications" + forceDt="5e3" + target="/Solvers/reservoirSystem"/> + - + name="outputs" + timeFrequency="5e4" + target="/Outputs/siloOutput"/> + - + name="restarts" + timeFrequency="2.5e5" + targetExactTimestep="0" + target="/Outputs/restartOutput"/> + - + name="fluidHM" + innerProductType="beiraoDaVeigaLipnikovManzini"/> + - + name="Region1" + cellBlocks="{ * }" + materialList="{ fluid, rock, relperm }"/> + - + name="wellRegion1" + materialList="{ fluid }"/> + - + name="wellRegion2" + materialList="{ fluid }"/> + - + name="wellRegion3" + materialList="{ fluid }"/> + - + name="fluid" + phaseNames="{ oil, gas, water }" + surfaceDensities="{ 800.0, 0.9907, 1022.0 }" + componentMolarWeight="{ 114e-3, 16e-3, 18e-3 }" + tableFiles="{ pvdo.txt, pvdg.txt, pvtw.txt }"/> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> + - + name="nullSolid"/> + - + name="rockPorosity" + defaultReferencePorosity="0.05" + referencePressure="0.0" + compressibility="1.0e-9"/> + - + name="relperm" + phaseNames="{ oil, gas, water }" + phaseMinVolumeFraction="{ 0.05, 0.05, 0.05 }" + phaseRelPermExponent="{ 2.0, 2.0, 1.5 }" + phaseRelPermMaxValue="{ 0.8, 0.9, 0.9 }"/> + - + name="rockPerm" + permeabilityComponents="{ 2.0e-16, 2.0e-16, 2.0e-16 }"/> + + - + name="initialPressure" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Region1/cb1" + fieldName="pressure" + scale="5e6"/> + - + name="initialFacePressure" + initialCondition="1" + setNames="{ all }" + objectPath="faceManager" + fieldName="facePressure" + scale="5e6"/> + + - + name="initialComposition_oil" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="0" + scale="0.6"/> + - + name="initialComposition_gas" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="1" + scale="0.399"/> + - + name="initialComposition_water" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Region1/cb1" + fieldName="globalCompFraction" + component="2" + scale="0.001"/> + - + name="siloOutput"/> + - + name="restartOutput"/> - \ No newline at end of file + diff --git a/inputFiles/compositionalMultiphaseWell/isothm_mass_inj_table.xml b/inputFiles/compositionalMultiphaseWell/isothm_mass_inj_table.xml index 44fa791c2e9..14076fab917 100644 --- a/inputFiles/compositionalMultiphaseWell/isothm_mass_inj_table.xml +++ b/inputFiles/compositionalMultiphaseWell/isothm_mass_inj_table.xml @@ -1,232 +1,229 @@ + + + name="coupledFlowAndWells" + flowSolverName="compflow" + wellSolverName="compositionalMultiphaseWell" + logLevel="4" + initialDt="1e2" + targetRegions="{ region, injwell }"> - + logLevel="4" + newtonTol="1.0e-3" + timeStepDecreaseIterLimit="0.41" + newtonMaxIter="40" + lineSearchAction="None"/> - + logLevel="4" + solverType="fgmres" + krylovTol="1e-4"/> + + name="compflow" + logLevel="4" + discretization="fluidTPFA" + temperature="368.15" + useMass="1" + initialDt="1e2" + maxCompFractionChange="0.5" + targetRegions="{ region }"> + + name="compositionalMultiphaseWell" + targetRegions="{ injwell }" + writeCSV="1" + logLevel="1" + useMass="1"> - - - - - - + name="WC_CO2_INJ" + logLevel="2" + type="injector" + control="massRate" + referenceElevation="-0.01" + enableCrossflow="0" + useSurfaceConditions="1" + surfacePressure="1.45e7" + surfaceTemperature="300.15" + targetTotalRate="15" + targetBHPTableName="totalBHPTable" + targetMassRateTableName="totalMassRateTable" + injectionTemperature="300.15" + injectionStream="{ 1.0, 0.000 }"/> + + + name="mesh1" + elementTypes="{ C3D8 }" + xCoords="{ 0, 2000 }" + yCoords="{ 0, 2000 }" + zCoords="{ 0, 2000 }" + nx="{ 1 }" + ny="{ 4 }" + nz="{ 1 }" + cellBlockNames="{ cb }"> + name="inj1" + wellRegionName="injwell" + wellControlsName="WC_CO2_INJ" + logLevel="1" + polylineNodeCoords="{ { 50.0, 30.0, 51.01 }, + { 50.0, 1450.0, 51.00 } }" + polylineSegmentConn="{ { 0, 1 } }" + radius="0.1" + numElementsPerSegment="2"> - + name="injector1_perf3" + distanceFromHead="171.93"/> - + name="injector1_perf17" + distanceFromHead="1334.738"/> + + + - + name="sink" + xMin="{ 89.99, 89.99, -0.01 }" + xMax="{ 101.01, 101.01, 1.01 }"/> + + + + maxTime="2.5e5"> - + name="outputs" + timeFrequency="2.5e4" + target="/Outputs/vtkOutput"/> + - + name="solverApplications" + maxEventDt="2.5e4" + target="/Solvers/coupledFlowAndWells"/> + - + name="restarts" + timeFrequency="2.5e4" + target="/Outputs/sidreRestart"/> + - - - - + + + - + name="fluidTPFA"/> + - + name="region" + cellBlocks="{ cb }" + materialList="{ fluid, rock, relperm }"/> - + name="injwell" + materialList="{ fluid, relperm }"/> + + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> - + name="nullSolid"/> - + name="rockPorosity" + defaultReferencePorosity="0.2" + referencePressure="0.0" + compressibility="1.0e-9"/> - + name="rockPerm" + permeabilityComponents="{ 1.0e-13, 1.0e-13, 1.0e-13 }"/> + - + name="fluid" + logLevel="1" + phaseNames="{ gas, water }" + componentNames="{ co2, water }" + componentMolarWeight="{ 44e-3, 18e-3 }" + phasePVTParaFiles="{ pvtgas.txt, pvtliquid.txt }" + flashModelParaFile="co2flash.txt"/> + - + name="relperm" + phaseNames="{ gas, water }" + phaseMinVolumeFraction="{ 0.0, 0.0 }" + phaseRelPermExponent="{ 1.5, 1.5 }" + phaseRelPermMaxValue="{ 0.9, 0.9 }"/> + + + - + name="initialPressure" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="pressure" + scale="9e6"/> - + name="initialTemperature" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="temperature" + scale="368.15"/> - + name="initialComposition_co2" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="0" + scale="0.005"/> - + name="initialComposition_water" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="1" + scale="0.995"/> + + - + name="vtkOutput"/> + - + name="sidreRestart"/> - \ No newline at end of file + diff --git a/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml b/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml index f03b18d24b8..d39421e36fc 100644 --- a/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml +++ b/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml @@ -1,238 +1,234 @@ + + + name="coupledFlowAndWells" + flowSolverName="compflow" + wellSolverName="compositionalMultiphaseWell" + logLevel="4" + initialDt="1e2" + targetRegions="{ region, injwell }"> - + logLevel="4" + newtonTol="1.0e-3" + timeStepDecreaseIterLimit="0.41" + newtonMaxIter="40" + lineSearchAction="None"/> - + logLevel="4" + solverType="fgmres" + krylovTol="1e-4"/> + + name="compflow" + logLevel="4" + discretization="fluidTPFA" + temperature="368.15" + useMass="1" + initialDt="1e2" + maxCompFractionChange="0.5" + targetRegions="{ region }"> + + name="compositionalMultiphaseWell" + targetRegions="{ injwell }" + writeCSV="1" + logLevel="1" + useMass="1"> - - - - - - + name="WC_CO2_INJ" + logLevel="2" + type="injector" + control="totalVolRate" + referenceElevation="-0.01" + enableCrossflow="0" + useSurfaceConditions="1" + surfacePressure="1.45e7" + surfaceTemperature="300.15" + targetBHPTableName="totalBHPTable" + targetTotalRateTableName="totalRateTable" + injectionTemperature="300.15" + injectionStream="{ 1.0, 0.000 }"/> + + + name="mesh1" + elementTypes="{ C3D8 }" + xCoords="{ 0, 2000 }" + yCoords="{ 0, 2000 }" + zCoords="{ 0, 2000 }" + nx="{ 1 }" + ny="{ 4 }" + nz="{ 1 }" + cellBlockNames="{ cb }"> + name="inj1" + wellRegionName="injwell" + wellControlsName="WC_CO2_INJ" + logLevel="1" + polylineNodeCoords="{ { 50.0, 30.0, 51.01 }, + { 50.0, 1450.0, 51.00 } }" + polylineSegmentConn="{ { 0, 1 } }" + radius="0.1" + numElementsPerSegment="2"> - + name="injector1_perf3" + distanceFromHead="171.93"/> - + name="injector1_perf17" + distanceFromHead="1334.738"/> + + + - + name="sink" + xMin="{ 89.99, 89.99, -0.01 }" + xMax="{ 101.01, 101.01, 1.01 }"/> + + + + maxTime="2.5e5"> - + name="outputs" + timeFrequency="2.5e4" + target="/Outputs/vtkOutput"/> + - + name="solverApplications" + maxEventDt="2.5e4" + target="/Solvers/coupledFlowAndWells"/> + - + name="restarts" + timeFrequency="2.5e4" + target="/Outputs/sidreRestart"/> + - - - - - - + + + + - + name="fluidTPFA"/> + - + name="region" + cellBlocks="{ cb }" + materialList="{ fluid, rock, relperm }"/> - + name="injwell" + materialList="{ fluid, relperm }"/> + + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> - + name="nullSolid"/> - + name="rockPorosity" + defaultReferencePorosity="0.2" + referencePressure="0.0" + compressibility="1.0e-9"/> - + name="rockPerm" + permeabilityComponents="{ 1.0e-13, 1.0e-13, 1.0e-13 }"/> + - + name="fluid" + logLevel="1" + phaseNames="{ gas, water }" + componentNames="{ co2, water }" + componentMolarWeight="{ 44e-3, 18e-3 }" + phasePVTParaFiles="{ pvtgas.txt, pvtliquid.txt }" + flashModelParaFile="co2flash.txt"/> + - + name="relperm" + phaseNames="{ gas, water }" + phaseMinVolumeFraction="{ 0.0, 0.0 }" + phaseRelPermExponent="{ 1.5, 1.5 }" + phaseRelPermMaxValue="{ 0.9, 0.9 }"/> + + + - + name="initialPressure" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="pressure" + scale="9e6"/> - + name="initialTemperature" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="temperature" + scale="368.15"/> - + name="initialComposition_co2" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="0" + scale="0.005"/> - + name="initialComposition_water" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/region/cb" + fieldName="globalCompFraction" + component="1" + scale="0.995"/> + + - + name="vtkOutput"/> + - + name="sidreRestart"/> - \ No newline at end of file + diff --git a/inputFiles/compositionalMultiphaseWell/simpleCo2InjTutorial_base.xml b/inputFiles/compositionalMultiphaseWell/simpleCo2InjTutorial_base.xml index edc2f004980..705b4934fb9 100644 --- a/inputFiles/compositionalMultiphaseWell/simpleCo2InjTutorial_base.xml +++ b/inputFiles/compositionalMultiphaseWell/simpleCo2InjTutorial_base.xml @@ -1,216 +1,226 @@ + + + + + name="coupledFlowAndWells" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + initialDt="1e2" + targetRegions="{ reservoir, wellRegion }"> - + newtonTol="1.0e-4" + lineSearchAction="None" + maxTimeStepCuts="10" + newtonMaxIter="40"/> - + solverType="fgmres" + preconditionerType="mgr" + krylovTol="1e-5"/> + - + name="compositionalMultiphaseFlow" + targetRegions="{ reservoir }" + discretization="fluidTPFA" + temperature="368.15" + maxCompFractionChange="0.2" + logLevel="1" + useMass="1"/> + + name="compositionalMultiphaseWell" + targetRegions="{ wellRegion }" + maxCompFractionChange="0.2" + logLevel="1" + useMass="1"> - - - - - + name="wellControls" + type="injector" + control="totalVolRate" + enableCrossflow="0" + referenceElevation="6650" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71" + targetBHP="5e7" + targetTotalRate="1.5" + injectionTemperature="368.15" + injectionStream="{ 1, 0 }"/> + + + - + name="reservoir" + cellBlocks="{ * }" + materialList="{ fluid, rock, relperm }"/> + - + name="wellRegion" + materialList="{ fluid }"/> + + + - + name="fluidTPFA"/> + + + - + name="fluid" + phaseNames="{ gas, water }" + componentNames="{ co2, water }" + componentMolarWeight="{ 44e-3, 18e-3 }" + phasePVTParaFiles="{ pvtgas.txt, pvtliquid.txt }" + flashModelParaFile="co2flash.txt"/> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> + - + name="nullSolid"/> + - + name="rockPorosity" + defaultReferencePorosity="0.05" + referencePressure="1.0e7" + compressibility="4.5e-10"/> + - + name="relperm" + phaseNames="{ gas, water }" + phaseMinVolumeFraction="{ 0.05, 0.30 }" + phaseRelPermExponent="{ 2.0, 2.0 }" + phaseRelPermMaxValue="{ 1.0, 1.0 }"/> + - + name="rockPerm" + permeabilityComponents="{ 1.0e-17, 1.0e-17, 3.0e-17 }"/> + + + + + + - + name="permy" + initialCondition="1" + component="1" + setNames="{ all }" + objectPath="ElementRegions/reservoir" + fieldName="rockPerm_permeability" + scale="1e-15" + functionName="permyFunc"/> + - + name="permz" + initialCondition="1" + component="2" + setNames="{ all }" + objectPath="ElementRegions/reservoir" + fieldName="rockPerm_permeability" + scale="1.5e-15" + functionName="permzFunc"/> + - + name="initialPressure" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/reservoir" + fieldName="pressure" + scale="1.25e7"/> + - + name="initialComposition_co2" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/reservoir" + fieldName="globalCompFraction" + component="0" + scale="0.0"/> + - - - + name="initialComposition_water" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/reservoir" + fieldName="globalCompFraction" + component="1" + scale="1.0"/> + + + - + name="simpleReservoirViz"/> + - + name="restartOutput"/> + - + name="timeHistoryOutput" + sources="{/Tasks/wellPressureCollection}" + filename="wellPressureHistory" /> + + + + - + name="wellPressureCollection" + objectPath="ElementRegions/wellRegion/wellRegionUniqueSubRegion" + fieldName="pressure" /> + + - - - + + - - + + - + interpolation="nearest" /> - \ No newline at end of file + + diff --git a/inputFiles/compositionalMultiphaseWell/staged_perf_base.xml b/inputFiles/compositionalMultiphaseWell/staged_perf_base.xml index 9e1b4a09e6e..302d728e9b4 100644 --- a/inputFiles/compositionalMultiphaseWell/staged_perf_base.xml +++ b/inputFiles/compositionalMultiphaseWell/staged_perf_base.xml @@ -1,197 +1,198 @@ + + + name="reservoirSystem" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="2" + targetRegions="{ reservoir, wellRegion1 }"> - + newtonTol="1.0e-8" + logLevel="4" + lineSearchAction="None" + newtonMaxIter="40"/> - + directParallel="0" /> + - + name="compositionalMultiphaseFlow" + logLevel="1" + discretization="fluidTPFA" + targetRegions="{ reservoir }" + temperature="297.15"/> + + name="compositionalMultiphaseWell" + logLevel="4" + writeCSV="1" + targetRegions="{ wellRegion1 }"> - - - - - + name="wellControls1" + type="producer" + control="BHP" + referenceElevation="0.5" + targetBHP="4e6" + targetPhaseRate="1e-3" + targetPhaseName="water"/> + + - + name="compflowStatistics" + flowSolverName="compositionalMultiphaseFlow" + logLevel="1" + computeCFLNumbers="1" + computeRegionStatistics="1"/> + + + maxTime="4.0e4"> - + name="statistics" + timeFrequency="2e2" + target="/Tasks/compflowStatistics"/> - + name="solverApplications" + forceDt="2.5e3" + target="/Solvers/reservoirSystem"/> + - + name="outputs" + timeFrequency="2.5e3" + target="/Outputs/vtkOutput"/> + - + name="restarts" + timeFrequency="1.25e4" + targetExactTimestep="0" + target="/Outputs/restartOutput"/> + - + name="fluidTPFA" + /> + - + name="reservoir" + cellBlocks="{ * }" + materialList="{ fluid, rock, relperm }"/> + - + name="wellRegion1" + materialList="{ fluid, relperm }"/> + + - + name="fluid" + phaseNames="{ gas, water }" + componentNames="{ co2, water }" + componentMolarWeight="{ 44e-3, 18e-3 }" + phasePVTParaFiles="{ pvtgas.txt, pvtliquid.txt }" + flashModelParaFile="co2flash.txt"/> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> + - + name="nullSolid"/> + - + name="rockPorosity" + defaultReferencePorosity="0.05" + referencePressure="0.0" + compressibility="1.0e-9"/> + - + name="relperm" + phaseNames="{ gas, water }" + phaseMinVolumeFraction="{ 0.1, 0.15 }" + phaseRelPermExponent="{ 2.0, 2.0 }" + phaseRelPermMaxValue="{ 0.8, 0.9 }"/> + - + name="rockPerm" + permeabilityComponents="{ 2.0e-16, 2.0e-16, 2.0e-16 }"/> + - + name="initialPressure" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/reservoir" + fieldName="pressure" + scale="1e6"/> + - + name="initialComposition_co2" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/reservoir" + fieldName="globalCompFraction" + component="0" + scale="0.0"/> + - + name="initialComposition_water" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/reservoir" + fieldName="globalCompFraction" + component="1" + scale="1.0"/> + - + name="equil" + objectPath="ElementRegions" + datumElevation="0" + datumPressure="2.214e7" + initialPhaseName="water" + componentNames="{ co2, water }" + componentFractionVsElevationTableNames="{ initCO2CompFracTable, + initWaterCompFracTable }" + temperatureVsElevationTableName="initTempTable"/> + + - + coordinates="{ -3000.0, 0.0 }" + values="{ 0.0, 0.0 }"/> + - + coordinates="{ -3000.0, 0.0 }" + values="{ 1.0, 1.0 }"/> + - + coordinates="{ -3000.0, 0.0 }" + values="{ 368, 288 }"/> + + - + name="vtkOutput"/> + - + name="restartOutput"/> - \ No newline at end of file + diff --git a/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_3d.xml b/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_3d.xml index 5270d3bc94d..388b15ca605 100644 --- a/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_3d.xml +++ b/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_3d.xml @@ -1,265 +1,261 @@ + + + name="reservoirSystem" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{ Channel, wellRegion1, wellRegion2 }"> - + newtonTol="1.0e-8" + lineSearchAction="None" + newtonMaxIter="40"/> - + directParallel="0"/> + - + name="compositionalMultiphaseFlow" + logLevel="1" + discretization="fluidTPFA" + targetRegions="{ Channel }" + temperature="368.15" + maxCompFractionChange="0.2" + useMass="1"/> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{ wellRegion1, wellRegion2 }" + maxCompFractionChange="0.2" + useMass="1"> - - - - - + name="wellControls1" + logLevel="1" + type="producer" + control="phaseVolRate" + referenceElevation="12" + targetBHP="1e6" + targetPhaseRateTableName="phaseRateTable" + targetPhaseName="water"/> - - - - - + name="wellControls2" + logLevel="1" + type="injector" + control="totalVolRate" + referenceElevation="12" + targetBHP="2e7" + targetTotalRateTableName="totalRateTable" + injectionTemperature="368.15" + injectionStream="{ 0.995, 0.005 }"/> + + + + name="mesh1" + elementTypes="{ C3D8 }" + xCoords="{ 0, 5, 10 }" + yCoords="{ 0, 5, 10 }" + zCoords="{ 0, 2.5, 5, 7.5, 10 }" + nx="{ 5, 5 }" + ny="{ 5, 5 }" + nz="{ 3, 3, 3, 3 }" + cellBlockNames="{ cb-0_0_0, cb-1_0_0, cb-0_1_0, cb-1_1_0, + cb-0_0_1, cb-1_0_1, cb-0_1_1, cb-1_1_1, + cb-0_0_2, cb-1_0_2, cb-0_1_2, cb-1_1_2, + cb-0_0_3, cb-1_0_3, cb-0_1_3, cb-1_1_3 }"> + + name="well_producer1" + wellRegionName="wellRegion1" + wellControlsName="wellControls1" + polylineNodeCoords="{ { 9.5, 0.5, 12 }, + { 9.5, 0.5, 0.05 } }" + polylineSegmentConn="{ { 0, 1 } }" + radius="0.1" + numElementsPerSegment="20"> - + name="producer1_perf1" + distanceFromHead="11.95"/> + + name="well_injector1" + logLevel="1" + wellRegionName="wellRegion2" + wellControlsName="wellControls2" + polylineNodeCoords="{ { 9.5, 0.2, 12 }, + { 9.5, 0.2, 9.5 } }" + polylineSegmentConn="{ { 0, 1 } }" + radius="0.1" + numElementsPerSegment="30"> - + name="injector1_perf1" + distanceFromHead="2.45"/> + + maxTime="2.5e5"> - + name="outputs" + timeFrequency="5e4" + target="/Outputs/siloOutput"/> + - + name="solverApplications" + forceDt="5e4" + target="/Solvers/reservoirSystem"/> + - + name="restarts" + timeFrequency="1.5e4" + targetExactTimestep="0" + target="/Outputs/restartOutput"/> + - + name="Channel" + cellBlocks="{ cb-1_0_0, cb-0_0_0, cb-0_0_1, cb-0_1_1, cb-0_1_2, cb-1_1_2, cb-1_1_3, cb-1_0_3 }" + materialList="{ fluid1, rock, relperm, cappres, diffusion }"/> + - + name="Barrier" + cellBlocks="{ cb-0_1_0, cb-1_1_0, cb-1_1_1, cb-1_0_1, cb-1_0_2, cb-0_0_2, cb-0_0_3, cb-0_1_3 }" + materialList="{ }"/> + - + name="wellRegion1" + materialList="{ fluid1 }"/> + - + name="wellRegion2" + materialList="{ fluid1 }"/> + - + name="fluidTPFA"/> + - + name="fluid1" + phaseNames="{ gas, water }" + componentNames="{ co2, water }" + componentMolarWeight="{ 44e-3, 18e-3 }" + phasePVTParaFiles="{ pvtgas.txt, pvtliquid.txt }" + flashModelParaFile="co2flash.txt"/> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> + - + name="nullSolid"/> + - + name="rockPorosity" + defaultReferencePorosity="0.1" + referencePressure="0.0" + compressibility="1.0e-9"/> + - + name="relperm" + phaseNames="{ gas, water }" + wettingNonWettingRelPermTableNames="{ waterRelativePermeabilityTable, + gasRelativePermeabilityTable }"/> + - + name="cappres" + phaseNames="{ gas, water }" + wettingNonWettingCapPressureTableName="waterCapillaryPressureTable"/> + - + name="rockPerm" + permeabilityComponents="{ 2.0e-16, 2.0e-16, 2.0e-16 }"/> + - + name="diffusion" + phaseNames="{ gas, water }" + defaultPhaseDiffusivityMultipliers="{ 20, 1 }" + diffusivityComponents="{ 1e-9, 1e-9, 1e-9 }"/> + + - + name="initialPressure_channel" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Channel" + fieldName="pressure" + scale="9e6"/> + - + name="initialComposition_co2" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Channel" + fieldName="globalCompFraction" + component="0" + scale="0.04"/> + - + name="initialComposition_water" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Channel" + fieldName="globalCompFraction" + component="1" + scale="0.96"/> + + - + name="waterRelativePermeabilityTable" + coordinateFiles="{ phaseVolFraction_water.txt }" + voxelFile="relPerm_water.txt"/> - + name="gasRelativePermeabilityTable" + coordinateFiles="{ phaseVolFraction_gas.txt }" + voxelFile="relPerm_gas.txt"/> - + name="waterCapillaryPressureTable" + coordinateFiles="{ phaseVolFraction_water.txt }" + voxelFile="capPres_water.txt"/> - + name="phaseRateTable" + inputVarNames="{time}" + coordinates="{0, 5.01e4, 5e5}" + values="{1e-7, 2e-7, 2e-7}" + interpolation="lower"/> - + name="totalRateTable" + inputVarNames="{time}" + coordinates="{0, 5.01e4, 5e5}" + values="{5e-8, 0, 0}" + interpolation="lower"/> + + - + name="siloOutput"/> + - + name="restartOutput"/> - \ No newline at end of file + diff --git a/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml b/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml index fa6d76dd609..b7e30e91dcb 100644 --- a/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml +++ b/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml @@ -1,235 +1,228 @@ + + + name="reservoirSystem" + flowSolverName="compositionalMultiphaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + initialDt="5e2" + targetRegions="{ Channel, wellRegion1, wellRegion2 }"> - + newtonTol="1.0e-6" + newtonMaxIter="40"/> - + directParallel="0"/> + - + name="compositionalMultiphaseFlow" + logLevel="1" + discretization="fluidHM" + targetRegions="{ Channel }" + temperature="368.15" + targetRelativePressureChangeInTimeStep="1" + targetPhaseVolFractionChangeInTimeStep="1" + maxCompFractionChange="0.2" + maxRelativePressureChange="0.2" + useMass="1"/> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{ wellRegion1, wellRegion2 }" + maxCompFractionChange="0.2" + maxRelativePressureChange="0.2" + useMass="1"> - - - - - + name="wellControls1" + type="producer" + control="BHP" + referenceElevation="12" + targetBHP="2e6" + targetPhaseRate="1e-7" + targetPhaseName="water"/> - - - - - + name="wellControls2" + type="injector" + control="totalVolRate" + referenceElevation="12" + targetBHP="2e7" + targetTotalRateTableName="totalRateTable" + injectionTemperature="368.15" + injectionStream="{ 0.995, 0.005 }"/> + + + name="mesh1" + file="staircase3d_tet_with_properties.vtu" + fieldsToImport="{ FluidComposition, PERM, PORO }" + fieldNamesInGEOS="{ globalCompFraction, rockPerm_permeability, rockPorosity_referencePorosity }" + partitionRefinement="1" + logLevel="2"> + + name="well_producer1" + wellRegionName="wellRegion1" + wellControlsName="wellControls1" + polylineNodeCoords="{ { 9.5, 0.5, 12 }, + { 9.5, 0.5, 0.05 } }" + polylineSegmentConn="{ { 0, 1 } }" + radius="0.1" + numElementsPerSegment="20"> - + name="producer1_perf1" + distanceFromHead="11.95"/> + + name="well_injector1" + wellRegionName="wellRegion2" + wellControlsName="wellControls2" + polylineNodeCoords="{ { 9.5, 0.2, 12 }, + { 9.5, 0.2, 9.5 } }" + polylineSegmentConn="{ { 0, 1 } }" + radius="0.1" + numElementsPerSegment="30"> - + name="injector1_perf1" + distanceFromHead="2.45"/> + + maxTime="2.5e5"> - + name="outputs" + timeFrequency="5e4" + target="/Outputs/vtkOutput"/> + - + name="solverApplications" + maxEventDt="5e4" + target="/Solvers/reservoirSystem"/> + - + name="restarts" + timeFrequency="1.5e4" + targetExactTimestep="0" + target="/Outputs/restartOutput"/> + - + name="Channel" + cellBlocks="{ * }" + materialList="{ fluid1, rock, relperm }"/> + - + name="wellRegion1" + materialList="{ fluid1 }"/> + - + name="wellRegion2" + materialList="{ fluid1 }"/> + - + name="fluidHM" + innerProductType="beiraoDaVeigaLipnikovManzini"/> + - + name="fluid1" + phaseNames="{ gas, water }" + componentNames="{ co2, water }" + componentMolarWeight="{ 44e-3, 18e-3 }" + phasePVTParaFiles="{ pvtgas.txt, pvtliquid.txt }" + flashModelParaFile="co2flash.txt"/> + - + name="rock" + solidModelName="nullSolid" + porosityModelName="rockPorosity" + permeabilityModelName="rockPerm"/> + - + name="nullSolid"/> + - + name="rockPorosity" + defaultReferencePorosity="0.1" + referencePressure="0.0" + compressibility="1.0e-9"/> + - + name="relperm" + phaseNames="{ gas, water }" + phaseMinVolumeFraction="{ 0.05, 0.05 }" + phaseRelPermExponent="{ 2, 1.5 }" + phaseRelPermMaxValue="{ 0.8, 0.9 }"/> + - + name="rockPerm" + permeabilityComponents="{ 2.0e-16, 2.0e-16, 2.0e-16 }"/> + - + name="initialPressure_channel" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Channel" + fieldName="pressure" + scale="9e6"/> + - + name="initialFacePressure_channel" + initialCondition="1" + setNames="{ all }" + objectPath="faceManager" + fieldName="facePressure" + scale="9e6"/> + - + name="initialComposition_co2" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Channel" + fieldName="globalCompFraction" + component="0" + scale="0.005"/> + - + name="initialComposition_water" + initialCondition="1" + setNames="{ all }" + objectPath="ElementRegions/Channel" + fieldName="globalCompFraction" + component="1" + scale="0.995"/> + - + name="totalRateTable" + inputVarNames="{time}" + coordinates="{0, 1.001e3, 3.5001e3, 5.001e3, 2.041e5, 1e6}" + values="{5e-7, 1e-7, 2e-7, 5e-7, 0, 0}" + interpolation="lower"/> + - + name="vtkOutput"/> + - + name="restartOutput"/> - \ No newline at end of file + diff --git a/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_fim.xml b/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_fim.xml index 0e705cf7491..0ca07929f8e 100644 --- a/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_fim.xml +++ b/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_fim.xml @@ -1,160 +1,151 @@ + + + - - - + + + + + name="reservoirSystem" + poromechanicsSolverName="multiphasePoroelasticity" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{ channel, barrier, wellRegion1, wellRegion2 }"> - + newtonTol="1.0e-8" + lineSearchAction="None" + newtonMaxIter="40"/> - + directParallel="0"/> + - + name="multiphasePoroelasticity" + solidSolverName="linearElasticity" + flowSolverName="twoPhaseFlow" + stabilizationType="Global" + stabilizationRegionNames="{ channel }" + logLevel="1" + targetRegions="{ channel }"/> + - + name="linearElasticity" + logLevel="1" + discretization="FE1" + targetRegions="{ channel, barrier }"/> + - + name="twoPhaseFlow" + logLevel="1" + discretization="fluidTPFA" + targetRelativePressureChangeInTimeStep="1" + targetPhaseVolFractionChangeInTimeStep="1" + targetRegions="{ channel }" + temperature="300" + useMass="1"/> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{ wellRegion1, wellRegion2 }" + maxCompFractionChange="0.2" + useMass="1"> - - - - - + name="wellControls1" + logLevel="1" + type="producer" + control="BHP" + referenceElevation="62.5" + targetBHP="9e6" + targetPhaseRateTableName="producerPhaseRateTable" + targetPhaseName="water"/> - - - - - + name="wellControls2" + logLevel="1" + type="injector" + control="totalVolRate" + referenceElevation="250" + targetBHP="1.5e7" + targetTotalRateTableName="injectorTotalRateTable" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71" + injectionTemperature="355" + injectionStream="{ 1.0, 0.0 }"/> + + + minTime="-1e11" + maxTime="1e7"> + - + name="outputs" + timeFrequency="1e6" + target="/Outputs/vtkOutput"/> + - + name="multiphasePoroelasticityEquilibrationStep" + targetTime="-1e11" + beginTime="-1e11" + target="/Tasks/multiphasePoroelasticityEquilibrationStep"/> + - + name="solverApplications1" + endTime="1e3" + target="/Solvers/reservoirSystem"/> - + name="solverApplications2" + beginTime="1e3" + maxEventDt="1e6" + target="/Solvers/reservoirSystem"/> + - + name="linearElasticityStatistics" + timeFrequency="1e6" + target="/Tasks/linearElasticityStatistics"/> - + name="twoPhaseFlowStatistics" + timeFrequency="1e6" + target="/Tasks/twoPhaseFlowStatistics"/> + - + name="restarts" + timeFrequency="5e6" + target="/Outputs/restartOutput"/> + - + name="vtkOutput" + fieldNames="{ initialPressure, skeletonChannel_density }"/> - + name="restartOutput"/> + + - + name="linearElasticityStatistics" + solidSolverName="linearElasticity" + logLevel="1"/> - - - + name="twoPhaseFlowStatistics" + flowSolverName="twoPhaseFlow" + logLevel="1" + computeCFLNumbers="1" + computeRegionStatistics="1"/> + + + - \ No newline at end of file + + diff --git a/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_sequential.xml b/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_sequential.xml index 924662385d8..e978595a49f 100755 --- a/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_sequential.xml +++ b/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_sequential.xml @@ -1,168 +1,158 @@ + + + - - - + + + + + name="reservoirSystem" + solidSolverName="linearElasticity" + reservoirAndWellsSolverName="reservoirAndWells" + logLevel="1" + targetRegions="{ channel }"> - + couplingType="Sequential" + subcycling="1" + newtonTol="1.0e-8" + lineSearchAction="None" + newtonMaxIter="100"/> - + directParallel="0"/> + - + name="linearElasticity" + logLevel="1" + discretization="FE1" + targetRegions="{ channel, barrier }"/> + + name="reservoirAndWells" + flowSolverName="twoPhaseFlow" + wellSolverName="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{ channel, wellRegion1, wellRegion2 }"> - + newtonTol="1.0e-8" + lineSearchAction="None" + newtonMaxIter="40"/> - + directParallel="0"/> + - + name="twoPhaseFlow" + logLevel="1" + discretization="fluidTPFA" + targetRelativePressureChangeInTimeStep="1" + targetPhaseVolFractionChangeInTimeStep="1" + targetRegions="{ channel }" + temperature="300" + useMass="1"/> + + name="compositionalMultiphaseWell" + logLevel="1" + targetRegions="{ wellRegion1, wellRegion2 }" + maxCompFractionChange="0.2" + useMass="1"> - - - - - + name="wellControls1" + logLevel="1" + type="producer" + control="BHP" + referenceElevation="62.5" + targetBHP="9e6" + targetPhaseRateTableName="producerPhaseRateTable" + targetPhaseName="water"/> - - - - - + name="wellControls2" + logLevel="1" + type="injector" + control="totalVolRate" + referenceElevation="250" + targetBHP="1.5e7" + targetTotalRateTableName="injectorTotalRateTable" + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71" + injectionTemperature="355" + injectionStream="{ 1.0, 0.0 }"/> + + + minTime="-1e11" + maxTime="1e7"> + - + name="outputs" + timeFrequency="1e6" + target="/Outputs/vtkOutput_seq"/> + - + name="multiphasePoroelasticityEquilibrationStep" + targetTime="-1e11" + beginTime="-1e11" + target="/Tasks/multiphasePoroelasticityEquilibrationStep"/> + - + name="solverApplications1" + endTime="1e3" + target="/Solvers/reservoirSystem"/> - + name="solverApplications2" + beginTime="1e3" + maxEventDt="1e6" + target="/Solvers/reservoirSystem"/> + - + name="linearElasticityStatistics" + timeFrequency="1e6" + target="/Tasks/linearElasticityStatistics"/> - + name="twoPhaseFlowStatistics" + timeFrequency="1e6" + target="/Tasks/twoPhaseFlowStatistics"/> + - + name="restarts" + timeFrequency="5e6" + target="/Outputs/restartOutput"/> + - + name="vtkOutput_seq" + fieldNames="{ initialPressure, skeletonChannel_density }"/> - + name="restartOutput"/> + + - + name="linearElasticityStatistics" + solidSolverName="linearElasticity" + logLevel="1"/> - + name="twoPhaseFlowStatistics" + flowSolverName="twoPhaseFlow" + logLevel="1" + computeCFLNumbers="1" + computeRegionStatistics="1"/> + - + logLevel="1" + name="multiphasePoroelasticityEquilibrationStep" + poromechanicsSolverName="reservoirSystem" + solidMechanicsStatisticsName="linearElasticityStatistics"/> + - \ No newline at end of file + + diff --git a/scripts/convert_well_schema.py b/scripts/convert_well_schema.py deleted file mode 100644 index dab3b4ffc5a..00000000000 --- a/scripts/convert_well_schema.py +++ /dev/null @@ -1,208 +0,0 @@ -import xml.etree.ElementTree as ET -import os -import optparse - -def print_xml_with_indent_and_attributes(ofn,tree, indent=" "): - import textwrap - ofs = open(ofn,"w") - root = tree.getroot() - ET.indent(tree, space=indent, level=0) # Indent nested elements - - def format_element(elem, level=0): - spaces = indent * level - tag_line = f"{spaces}<{elem.tag}" - attrib_lines = [] - for k, v in elem.attrib.items(): - v =v.replace(" ","") - v = v.replace(",",", ") - attr_str = f'{k}="{v}"' - wrapped = textwrap.wrap(attr_str, width=100, break_long_words=False, break_on_hyphens=False) - for i, line in enumerate(wrapped): - if i == 0: - attrib_lines.append(f"{indent * (level + 1)}{indent}{line}") - else: - # Extra indent for all rows after the first - attrib_lines.append(f"{indent * (level + 2)}{" "+line}") - if attrib_lines: - tag_line += "\n" + "\n".join(attrib_lines) - tag_line += f">" - else: - istrt = tag_line.find("<") - if istrt > -1: - tag_line += ">" - else: - tag_line += ">" - lines = [tag_line] - if elem.text and elem.text.strip(): - lines.append(f"{spaces}{indent}{elem.text.strip()}") - for child in elem: - lines.append(format_element(child, level + 1)) - lines.append(f"{spaces}") - return "\n".join(lines) - ofs.write(format_element(root)) - ofs.close() - -def update_or_add_constraint_element(xml_file, ofs,delete_old_schema,add_we,estimatorSolves): - #tree = ET.parse(xml_file) - with open(xml_file, 'rb') as xml_file: - tree = ET.parse(xml_file) - root = tree.getroot() - compoFluidModel = True - for elem in root.iter(): - #print(f"Tag: {elem.tag}, Attributes: {elem.attrib}, Text: {elem.text}") - - if elem.tag == "CompositionalMultiphaseWell" or elem.tag == "SinglePhaseWell": - if elem.tag == "SinglePhaseWell": - compoFluidModel = False - if "writeCSV" not in elem.attrib: - esolves = '"'+str(estimatorSolves)+'"' - elem.set("writeCSV","1") - if add_we: - elem.set("useNewCode", "1") - nlsTag="NonlinearSolverParameters" - nlsAttributes={} - nlsAttributes["newtonTol"]="1.0e-8" - nlsAttributes["lineSearchAction"]="None" - nlsAttributes["newtonMaxIter"]="20" - elem.insert(0,ET.Element(nlsTag,nlsAttributes)) - lsTag="LinearSolverParamters" - lsAttributes={} - lsAttributes["directParallel"]="0" - elem.insert(0,ET.Element(lsTag,lsAttributes)) - - if elem.tag == "WellControls": - #print(f"Tag: {elem.tag}, Attributes: {elem.attrib}, Text: {elem.text}") - if "control" in elem.attrib: - if delete_old_schema: - elem.attrib.pop("control") - if add_we: - elem.set("estimateWellSolution",str(estimatorSolves)) - isProducer = elem.attrib['type'] == 'producer' - if isProducer: - constraintType="Production" - pressureType="Minimum" - else: - constraintType="Injection" - pressureType="Maximum" - # setup phase constraint - if 'targetPhaseName' in elem.attrib: - phaseConstraintTag= "Phase"+constraintType+"Constraint" - phaseConstraintAttributes={} - phaseConstraintAttributes["name"]="max"+elem.attrib['targetPhaseName'].lower() +"prod" if isProducer else "max"+elem.attrib['targetPhaseName'].lower() +"inj" - if 'targetPhaseName' in elem.attrib: - phaseConstraintAttributes["phaseName"] = elem.attrib['targetPhaseName'] - if delete_old_schema: - elem.attrib.pop("targetPhaseName") - if "targetPhaseRateTableName" in elem.attrib: - phaseConstraintAttributes["constraintScheduleTableName"]=elem.attrib["targetPhaseRateTableName"] - if delete_old_schema: - elem.attrib.pop("targetPhaseRateTableName") - elif "targetPhaseRate" in elem.attrib: - phaseConstraintAttributes["phaseRate"]=elem.attrib["targetPhaseRate"] - if delete_old_schema: - elem.attrib.pop("targetPhaseRate") - else: - print("error missing phase rate info") - if not isProducer: - if compoFluidModel: - if "injectionStream" in elem: - phaseConstraintAttributes["injectionStream"]=elem.attrib["injectionStream"] - phaseConstraintAttributes["injectionTemperature"]=elem.attrib["injectionTemperature"] - if delete_old_schema: - elem.attrib.pop("injectionStream") - elem.attrib.pop("injectionTemperature") - else: - print("error missinging injectionStream ",elem) - - - elem.append(ET.Element(phaseConstraintTag,phaseConstraintAttributes)) - - # setup pressure constraint - pressureConstraintTag= pressureType+"BHPConstraint" - pressureConstraintAttributes={} - pressureConstraintAttributes["name"]="minbhp" if isProducer else "maxbhp" - if 'targetBHPTableName' in elem.attrib: - pressureConstraintAttributes["constraintScheduleTableName"]=elem.attrib["targetBHPTableName"] - if delete_old_schema: - elem.attrib.pop("targetBHPTableName") - elif 'targetBHP' in elem.attrib: - pressureConstraintAttributes["targetBHP"]=elem.attrib["targetBHP"] - if delete_old_schema: - elem.attrib.pop("targetBHP") - else: - print('error missing bhp info') - - if 'referenceElevation' in elem.attrib: - pressureConstraintAttributes["referenceElevation"]=elem.attrib["referenceElevation"] - if delete_old_schema: - elem.attrib.pop("referenceElevation") - else: - print('error missing bhp referenceElevation') - - elem.append(ET.Element(pressureConstraintTag,pressureConstraintAttributes)) - - totalVolRateTag= "TotalVol"+constraintType+"Constraint" - totalVolRateAttributes={} - if 'targetTotalRate' in elem.attrib or 'targetTotalRateTableName' in elem.attrib: - if 'targetTotalRate' in elem.attrib: - totalVolRateAttributes["volumeRate"]=elem.attrib["targetTotalRate"] - if delete_old_schema: - elem.attrib.pop("targetTotalRate") - if 'targetTotalRateTableName' in elem.attrib: - totalVolRateAttributes["constraintScheduleTableName"]=elem.attrib["targetTotalRateTableName"] - if delete_old_schema: - elem.attrib.pop("targetTotalRateTableName") - if not isProducer: - if compoFluidModel: - totalVolRateAttributes["injectionStream"]=elem.attrib["injectionStream"] - totalVolRateAttributes["injectionTemperature"]=elem.attrib["injectionTemperature"] - if delete_old_schema: - elem.attrib.pop("injectionStream") - elem.attrib.pop("injectionTemperature") - elem.append(ET.Element(totalVolRateTag,totalVolRateAttributes)) - print_xml_with_indent_and_attributes(ofs,tree) - - -def main1(ifs,ofs,delete_old_schema,add_we,estimatorSolves): - update_or_add_constraint_element(ifs,ofs,delete_old_schema,add_we,estimatorSolves) - - -if __name__ == "__main__": - - bdir = "/Users/byer3/geos_models/geos-total-dataset/GreatNorthernLight/GNL_FlowOnly/depletion" - #fn = "/Users/byer3/opm/opm-simulators/tests/include/b1_vfp_flowline.inc" - ifn = 'GNL_BO_WELL_FULLRATE.xml' - ofn = 'GNL_BO_WELL_FULLRATE_WE2.xml' - #ofn="/Users/byer3/GEOS-DEV-1105/we0708/inputFiles/compositionalMultiphaseWell/include" - #main1(os.path.join(bdir,ifn),os.path.join(bdir,ofn)) - - parser = optparse.OptionParser() - parser.add_option("-s", "--sourcefile", type="str" ,default="", help="source file") - parser.add_option("-t", "--targetfile", type="str" ,default="", help="target file") - parser.add_option("-a", "--add", action="store_true",default=False, help="add we strings") - parser.add_option("-e", "--estimatorSolves", type="int" ,default=0, help="when to use estimator") - parser.add_option("-d", "--delete", action="store_true",default=False, help="delete old schema") - parser.add_option("-r", "--replace", action="store_true",default=False, help="in place substitution") - parser.add_option("-f", "--file", type="str" ,default="", help="file with list of files to process") - (options, args) = parser.parse_args() - if options.file: - ifs = open(options.file,"r") - for f in ifs: - options.sourcefile=f.rstrip().lstrip() - if options.replace: - fn1=f.rstrip().lstrip() - fn2=fn1 - else: - fn1 , fn2 = f.split() - fn1=fn1.rsplit().lsplit() - fn2=fn2.rsplit().lsplit() - print("Processing ",fn1,fn2,options.add,options.estimatorSolves) - main1(fn1,fn2,options.delete,options.add,options.estimatorSolves) - else: - if options.replace: - options.targetfile=options.sourcefile - main1(options.sourcefile,options.targetfile,options.delete,options.add,options.estimatorSolves) - - - - print('Finished') \ No newline at end of file From e39ccf161e11746224836a725e85f3c91205a95b Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Thu, 23 Oct 2025 11:46:37 -0700 Subject: [PATCH 17/71] xml with new constraint schema, try 2 --- .../1D_100cells/1D_benchmark.xml | 682 ++++++++++-------- .../soreideWhitson/1D_100cells/1D_smoke.xml | 682 ++++++++++-------- .../class09_pb3_drainageOnly_direct_base.xml | 84 ++- ...lass09_pb3_drainageOnly_iterative_base.xml | 143 ++-- .../class09_pb3_hystRelperm_direct_base.xml | 90 +-- ...class09_pb3_hystRelperm_iterative_base.xml | 91 +-- .../benchmarks/Egg/deadOilEgg_base_direct.xml | 233 +++--- .../Egg/deadOilEgg_base_iterative.xml | 233 +++--- .../black_oil_wells_saturated_3d.xml | 124 ++-- .../black_oil_wells_saturated_3d_stone2.xml | 175 +++-- .../black_oil_wells_unsaturated_3d.xml | 88 +-- .../black_oil_wells_unsaturated_3d_stone2.xml | 518 ++++++------- .../compositional_multiphase_wells_1d.xml | 44 +- .../compositional_multiphase_wells_2d.xml | 64 +- .../dead_oil_wells_2d.xml | 66 +- .../dead_oil_wells_hybrid_2d.xml | 58 +- .../isothm_mass_inj_table.xml | 62 +- .../isothm_vol_inj_table.xml | 72 +- .../simpleCo2InjTutorial_base.xml | 97 ++- .../staged_perf_base.xml | 64 +- .../staircase_co2_wells_3d.xml | 76 +- .../staircase_co2_wells_hybrid_3d.xml | 48 +- .../PoroElastic_staircase_co2_3d_fim.xml | 71 +- ...oroElastic_staircase_co2_3d_sequential.xml | 69 +- ...roElastic_staircase_singlephase_3d_fim.xml | 66 +- ...ic_staircase_singlephase_3d_sequential.xml | 67 +- ...echanics_FaultModel_well_fim_new_smoke.xml | 75 +- ...oromechanics_FaultModel_well_fim_smoke.xml | 75 +- ...echanics_FaultModel_well_seq_new_smoke.xml | 70 +- ...oromechanics_FaultModel_well_seq_smoke.xml | 70 +- .../thermalCompressibleWell_base.xml | 35 +- .../compressible_single_phase_wells_1d.xml | 33 +- ...sible_single_phase_wells_1d_skinFactor.xml | 37 +- ...pressible_single_phase_wells_hybrid_1d.xml | 33 +- .../incompressible_single_phase_wells_2d.xml | 51 +- ...pressible_single_phase_wells_hybrid_2d.xml | 48 +- .../singlePhaseWell/perf_status_test.xml | 68 +- .../staircase_single_phase_wells_3d.xml | 48 +- ...staircase_single_phase_wells_hybrid_3d.xml | 38 +- src/coreComponents/schema/schema.xsd.other | 4 +- 40 files changed, 2576 insertions(+), 2176 deletions(-) diff --git a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml index 89b9cc7dc86..7bb21f00c3b 100644 --- a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml +++ b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml @@ -1,294 +1,388 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml index 19a577bde98..54375f72202 100644 --- a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml +++ b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml @@ -1,294 +1,388 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_direct_base.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_direct_base.xml index f2c31503e8a..81c1480a9f2 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_direct_base.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_direct_base.xml @@ -1,8 +1,6 @@ - - + useMass="1" + writeCSV="1"> + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71"> + + + - + - + + name="fluidTPFA"/> @@ -80,13 +83,16 @@ solidModelName="nullSolid" porosityModelName="rockPorosity" permeabilityModelName="rockPerm"/> + + + @@ -94,9 +100,8 @@ - + wettingNonWettingRelPermTableNames="{ waterRelativePermeabilityTable, gasRelativePermeabilityTable }"/> + - - - + + + + - @@ -152,11 +157,13 @@ name="initCO2CompFracTable" coordinates="{ -3238.2, -2506.13 }" values="{ 0.000001, 0.000001 }"/> + - @@ -165,37 +172,36 @@ name="waterRelativePermeabilityTable" coordinateFiles="{ tables/phaseVolumeFraction_water.txt }" voxelFile="tables/relPerm_water.txt"/> + + voxelFile="tables/relPerm_gas.txt"/> - + voxelFile="tables/capPres_water.txt"/> - + interpolation="linear"/> - + interpolation="linear"/> - - diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_iterative_base.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_iterative_base.xml index 8e76b08905b..cc1fa75b4e1 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_iterative_base.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_iterative_base.xml @@ -1,10 +1,7 @@ - - - - - - - + useMass="1" + writeCSV="1"> + surfaceTemperature="288.71"> + + + + surfaceTemperature="288.71"> + + + + surfaceTemperature="288.71"> + + + - - - - + + name="fluidTPFA"/> - - - + + + - - - + wettingNonWettingRelPermTableNames="{ waterRelativePermeabilityTable, gasRelativePermeabilityTable }"/> - - - - - - - - + + + - @@ -204,11 +197,13 @@ name="initCO2CompFracTable" coordinates="{ -3238.2, -2506.13 }" values="{ 0.000001, 0.000001 }"/> + - @@ -217,43 +212,43 @@ name="waterRelativePermeabilityTable" coordinateFiles="{ tables/phaseVolumeFraction_water.txt }" voxelFile="tables/relPerm_water.txt"/> + + voxelFile="tables/relPerm_gas.txt"/> - + voxelFile="tables/capPres_water.txt"/> - + interpolation="linear"/> - + interpolation="linear"/> - diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_direct_base.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_direct_base.xml index c731abcf696..e27b40839fa 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_direct_base.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_direct_base.xml @@ -1,8 +1,6 @@ - - + useMass="1" + writeCSV="1"> + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71"> + + + - + - + + name="fluidTPFA"/> @@ -80,26 +83,27 @@ solidModelName="nullSolid" porosityModelName="rockPorosity" permeabilityModelName="rockPerm"/> + + + - - + - - - - - + + + + - @@ -157,59 +159,61 @@ name="initCO2CompFracTable" coordinates="{ -3238.2, -2506.13 }" values="{ 0.000001, 0.000001 }"/> + + - + voxelFile="tables/capPres_water.txt"/> - + interpolation="linear"/> - + interpolation="linear"/> - - + + + - - diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_iterative_base.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_iterative_base.xml index ee1af0ef88d..2cdefa8fece 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_iterative_base.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_iterative_base.xml @@ -1,8 +1,6 @@ - - + useMass="1" + writeCSV="1"> + surfaceTemperature="288.71"> + + + - + - + + name="fluidTPFA"/> @@ -84,28 +87,27 @@ solidModelName="nullSolid" porosityModelName="rockPorosity" permeabilityModelName="rockPerm"/> + + + - - - - + - - + + + + - @@ -161,10 +163,12 @@ name="initCO2CompFracTable" coordinates="{ -3238.2, -2506.13 }" values="{ 0.000001, 0.000001 }"/> + + + + voxelFile="tables/relPerm_gas.txt"/> + voxelFile="tables/capPres_water.txt"/> - + interpolation="linear"/> - + interpolation="linear"/> - + + + - - diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml index 048e88999d7..e36f6f4ef20 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml @@ -1,7 +1,6 @@ - + useMass="1" + writeCSV="1"> + type="producer"> + + + - - - + type="producer"> + + + + type="producer"> + + + + type="producer"> + + + + type="injector"> + + + + type="injector"> + + + + type="injector"> + + + + type="injector"> + + + + type="injector"> + + + + type="injector"> + + + + type="injector"> + + + + type="injector"> + + + - - - - - - - - @@ -279,7 +316,6 @@ materialList="{ fluid }"/> - - - - - @@ -373,11 +405,8 @@ - - - - - diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_iterative.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_iterative.xml index 615688bef78..0478abfa3e4 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_iterative.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_iterative.xml @@ -1,7 +1,6 @@ - + useMass="1" + writeCSV="1"> + type="producer"> + + + - - - + type="producer"> + + + + type="producer"> + + + + type="producer"> + + + + type="injector"> + + + + type="injector"> + + + + type="injector"> + + + + type="injector"> + + + + type="injector"> + + + + type="injector"> + + + + type="injector"> + + + + type="injector"> + + + - - - - - - - - @@ -281,7 +318,6 @@ materialList="{ fluid }"/> - - - - - @@ -375,11 +407,8 @@ - - - - - diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d.xml index 7ebac080cbc..348143f043f 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d.xml @@ -2,7 +2,6 @@ - - + + useMass="1" + writeCSV="1"> + type="producer"> + + + + type="injector"> + + + - - - - + - + - + - @@ -148,12 +152,14 @@ name="region" cellBlocks="{ * }" materialList="{ fluid, rock, relperm, cappres }"/> + + + materialList="{ fluid }"/> @@ -163,7 +169,7 @@ surfaceDensities="{ 800.907131537, 0.856234902739, 1020.3440 }" componentMolarWeight="{ 120e-3, 25e-3, 18e-3 }" tableFiles="{ pvto_bo.txt, pvtg_norv_bo.txt, pvtw_bo.txt }"/> - + - + - - + + + scale="0.2"/> + - + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, 0.2500, 0.3025, 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000 }"/> + + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, 0.2500, 0.3025, 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000 }"/> + + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, 0.2500, 0.3025, 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000 }"/> + + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, 0.2500, 0.3025, 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000 }"/> + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 10000, 9025, 8100, 7225, 6400, 5625, 4900, 4225, 3600, 3025, 2500, 2025, 1600, 1225, 900, 625, 400, 225, 100, 25, 0 }"/> + - + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 50, 200, 450, 800, 1250, 1800, 2450, 3200, 4050, 5000, 6050, 7200, 8450, 9800, 11250, 12800, 14450, 16200, 18050, 20000 }"/> - + - + - + - + - diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml index ce669961545..66668c64b1b 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml @@ -2,7 +2,6 @@ - - + + useMass="1" + writeCSV="1"> + type="producer"> + + + + type="injector"> + + + - - - - - - - + + + + + + - - + - + - + - @@ -147,12 +152,14 @@ name="region" cellBlocks="{ * }" materialList="{ fluid, rock, relperm, cappres }"/> + + + materialList="{ fluid }"/> @@ -162,7 +169,7 @@ surfaceDensities="{ 800.907131537, 0.856234902739, 1020.3440 }" componentMolarWeight="{ 120e-3, 25e-3, 18e-3 }" tableFiles="{ pvto_bo.txt, pvtg_norv_bo.txt, pvtw_bo.txt }"/> - + - + - - + + + scale="0.2"/> + - + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, 0.2500, 0.3025, 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000 }"/> + + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, 0.2500, 0.3025, 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000 }"/> + + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, 0.2500, 0.3025, 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000 }"/> + + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 0.0025, 0.0100, 0.0225, 0.0400, 0.0625, 0.0900, 0.1225, 0.1600, 0.2025, 0.2500, 0.3025, 0.3600, 0.4225, 0.4900, 0.5625, 0.6400, 0.7225, 0.8100, 0.9025, 1.0000 }"/> + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 10000, 9025, 8100, 7225, 6400, 5625, 4900, 4225, 3600, 3025, 2500, 2025, 1600, 1225, 900, 625, 400, 225, 100, 25, 0 }"/> + - + coordinates="{ 0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.5, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00 }" + values="{ 0, 50, 200, 450, 800, 1250, 1800, 2450, 3200, 4050, 5000, 6050, 7200, 8450, 9800, 11250, 12800, 14450, 16200, 18050, 20000 }"/> - + - + - + - + - diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml index 323b9a144c6..5495defa879 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml @@ -2,7 +2,6 @@ - - + + + useMass="1" + writeCSV="1"> + type="producer"> + + + + type="injector"> + + + - - - - - + - - + - + - @@ -148,12 +153,14 @@ name="region" cellBlocks="{ * }" materialList="{ fluid, rock, relperm }"/> + + + materialList="{ fluid }"/> @@ -163,7 +170,7 @@ surfaceDensities="{ 800.907131537, 0.856234902739, 1020.3440 }" componentMolarWeight="{ 120e-3, 25e-3, 18e-3 }" tableFiles="{ pvto_bo.txt, pvtg_norv_bo.txt, pvtw_bo.txt }"/> - + - - + + + scale="0.1"/> + - + - + - + name="vtkOutput"/> + - - diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml index ea41c8adf9c..a29b0d7c615 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml @@ -1,260 +1,266 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_1d.xml b/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_1d.xml index bea2c48815d..baae030fefc 100644 --- a/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_1d.xml +++ b/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_1d.xml @@ -26,24 +26,33 @@ + targetRegions="{ wellRegion1, wellRegion2 }" + writeCSV="1"> + type="producer"> + + + + type="injector"> + + + @@ -58,7 +67,6 @@ ny="{ 1 }" nz="{ 1 }" cellBlockNames="{ cb1 }"> - - + name="fluidTPFA"/> @@ -175,7 +181,6 @@ - - - + targetRegions="{ wellRegion1, wellRegion2, wellRegion3 }" + writeCSV="1"> + type="producer"> + + + + type="producer"> + + + + type="injector"> + + + - - @@ -69,7 +79,6 @@ ny="{ 20 }" nz="{ 1 }" cellBlockNames="{ cb1 }"> - - - + name="fluidTPFA"/> @@ -223,7 +229,6 @@ - - + maxCompFractionChange="0.1" + writeCSV="1"> + surfaceTemperature="297.15"> + + + + surfaceTemperature="297.15"> + + + + surfaceTemperature="297.15"> + + + @@ -78,7 +91,6 @@ ny="{ 20 }" nz="{ 1 }" cellBlockNames="{ cb1 }"> - - - + name="fluidTPFA"/> @@ -223,7 +232,6 @@ - - - - + + maxCompFractionChange="0.1" + writeCSV="1"> + surfaceTemperature="297.15"> + + + + surfaceTemperature="297.15"> + + + + surfaceTemperature="297.15"> + + + @@ -77,7 +90,6 @@ ny="{ 20 }" nz="{ 1 }" cellBlockNames="{ cb1 }"> - - - - - - + targetRegions="{ region }"/> - + surfaceTemperature="300.15"> + + + + @@ -83,10 +85,8 @@ - - @@ -94,8 +94,6 @@ name="sink" xMin="{ 89.99, 89.99, -0.01 }" xMax="{ 101.01, 101.01, 1.01 }"/> - - - - @@ -143,25 +142,28 @@ name="region" cellBlocks="{ cb }" materialList="{ fluid, rock, relperm }"/> + - + + + @@ -181,11 +183,9 @@ phaseMinVolumeFraction="{ 0.0, 0.0 }" phaseRelPermExponent="{ 1.5, 1.5 }" phaseRelPermMaxValue="{ 0.9, 0.9 }"/> - - + + + - diff --git a/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml b/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml index d39421e36fc..4a63baf335e 100644 --- a/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml +++ b/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml @@ -10,7 +10,7 @@ initialDt="1e2" targetRegions="{ region, injwell }"> - + targetRegions="{ region }"/> - + surfaceTemperature="300.15"> + + + + @@ -82,10 +85,8 @@ - - @@ -93,8 +94,6 @@ name="sink" xMin="{ 89.99, 89.99, -0.01 }" xMax="{ 101.01, 101.01, 1.01 }"/> - - - - - @@ -148,25 +149,28 @@ name="region" cellBlocks="{ cb }" materialList="{ fluid, rock, relperm }"/> + - + + + @@ -186,11 +190,9 @@ phaseMinVolumeFraction="{ 0.0, 0.0 }" phaseRelPermExponent="{ 1.5, 1.5 }" phaseRelPermMaxValue="{ 0.9, 0.9 }"/> - - + + + - diff --git a/inputFiles/compositionalMultiphaseWell/simpleCo2InjTutorial_base.xml b/inputFiles/compositionalMultiphaseWell/simpleCo2InjTutorial_base.xml index 705b4934fb9..d5522a2e86e 100644 --- a/inputFiles/compositionalMultiphaseWell/simpleCo2InjTutorial_base.xml +++ b/inputFiles/compositionalMultiphaseWell/simpleCo2InjTutorial_base.xml @@ -1,8 +1,6 @@ - - + useMass="1" + writeCSV="1"> + useSurfaceConditions="1" + surfacePressure="101325" + surfaceTemperature="288.71"> + + + - - - + - - - + - - - - - - - - @@ -185,42 +177,37 @@ - + sources="{ /Tasks/wellPressureCollection }" + filename="wellPressureHistory"/> - - - + fieldName="pressure"/> - + - - - - - + + + + + - diff --git a/inputFiles/compositionalMultiphaseWell/staged_perf_base.xml b/inputFiles/compositionalMultiphaseWell/staged_perf_base.xml index 302d728e9b4..f57c8e7e745 100644 --- a/inputFiles/compositionalMultiphaseWell/staged_perf_base.xml +++ b/inputFiles/compositionalMultiphaseWell/staged_perf_base.xml @@ -10,11 +10,11 @@ targetRegions="{ reservoir, wellRegion1 }"> + directParallel="0"/> + type="producer"> + + + - - + + name="fluidTPFA"/> @@ -91,7 +93,6 @@ - @@ -158,34 +159,31 @@ scale="1.0"/> - + name="equil" + objectPath="ElementRegions" + datumElevation="0" + datumPressure="2.214e7" + initialPhaseName="water" + componentNames="{ co2, water }" + componentFractionVsElevationTableNames="{ initCO2CompFracTable, initWaterCompFracTable }" + temperatureVsElevationTableName="initTempTable"/> + name="initCO2CompFracTable" + coordinates="{ -3000.0, 0.0 }" + values="{ 0.0, 0.0 }"/> + name="initWaterCompFracTable" + coordinates="{ -3000.0, 0.0 }" + values="{ 1.0, 1.0 }"/> - + name="initTempTable" + coordinates="{ -3000.0, 0.0 }" + values="{ 368, 288 }"/> diff --git a/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_3d.xml b/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_3d.xml index 388b15ca605..09782b123a6 100644 --- a/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_3d.xml +++ b/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_3d.xml @@ -30,31 +30,38 @@ logLevel="1" targetRegions="{ wellRegion1, wellRegion2 }" maxCompFractionChange="0.2" - useMass="1"> + useMass="1" + writeCSV="1"> + logLevel="1" + type="producer"> + + + + logLevel="1" + type="injector"> + + + - - - + cellBlockNames="{ cb-0_0_0, cb-1_0_0, cb-0_1_0, cb-1_1_0, cb-0_0_1, cb-1_0_1, cb-0_1_1, cb-1_1_1, cb-0_0_2, cb-1_0_2, cb-0_1_2, cb-1_1_2, cb-0_0_3, cb-1_0_3, cb-0_1_3, cb-1_1_3 }"> - + wettingNonWettingRelPermTableNames="{ waterRelativePermeabilityTable, gasRelativePermeabilityTable }"/> - @@ -222,35 +222,37 @@ scale="0.96"/> - + + voxelFile="relPerm_gas.txt"/> + + voxelFile="capPres_water.txt"/> + + - diff --git a/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml b/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml index b7e30e91dcb..85eca6c8f16 100644 --- a/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml +++ b/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml @@ -34,29 +34,37 @@ targetRegions="{ wellRegion1, wellRegion2 }" maxCompFractionChange="0.2" maxRelativePressureChange="0.2" - useMass="1"> + useMass="1" + writeCSV="1"> + type="producer"> + + + + type="injector"> + + + - - - - + diff --git a/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_fim.xml b/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_fim.xml index 0ca07929f8e..a2ba64182bd 100644 --- a/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_fim.xml +++ b/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_fim.xml @@ -1,13 +1,12 @@ - - - + + - - + + targetRegions="{ channel, barrier }"/> @@ -52,37 +51,44 @@ logLevel="1" targetRegions="{ wellRegion1, wellRegion2 }" maxCompFractionChange="0.2" - useMass="1"> + useMass="1" + writeCSV="1"> + logLevel="1" + type="producer"> + + + + surfaceTemperature="288.71"> + + + - - + + - + + - + - - - diff --git a/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_sequential.xml b/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_sequential.xml index e978595a49f..350ae94d062 100755 --- a/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_sequential.xml +++ b/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_sequential.xml @@ -1,13 +1,12 @@ - - - + + - - + + targetRegions="{ channel, barrier }"/> @@ -59,37 +58,44 @@ logLevel="1" targetRegions="{ wellRegion1, wellRegion2 }" maxCompFractionChange="0.2" - useMass="1"> + useMass="1" + writeCSV="1"> + logLevel="1" + type="producer"> + + + + surfaceTemperature="288.71"> + + + - - + + - + + - + - - diff --git a/inputFiles/poromechanics/PoroElastic_staircase_singlephase_3d_fim.xml b/inputFiles/poromechanics/PoroElastic_staircase_singlephase_3d_fim.xml index 95f2090ada1..0fca99382a5 100644 --- a/inputFiles/poromechanics/PoroElastic_staircase_singlephase_3d_fim.xml +++ b/inputFiles/poromechanics/PoroElastic_staircase_singlephase_3d_fim.xml @@ -1,13 +1,12 @@ - - - + + - - + + targetRegions="{ channel, barrier }"/> + targetRegions="{ wellRegion1, wellRegion2 }" + writeCSV="1"> + logLevel="1" + type="producer"> + + + + surfacePressure="101325"> + + + - - + minTime="-1e11" + maxTime="1e7"> - + + - + + - - + + - diff --git a/inputFiles/poromechanics/PoroElastic_staircase_singlephase_3d_sequential.xml b/inputFiles/poromechanics/PoroElastic_staircase_singlephase_3d_sequential.xml index 0c952c6934f..88ad501f362 100755 --- a/inputFiles/poromechanics/PoroElastic_staircase_singlephase_3d_sequential.xml +++ b/inputFiles/poromechanics/PoroElastic_staircase_singlephase_3d_sequential.xml @@ -1,13 +1,12 @@ - - - + + - - + + targetRegions="{ channel, barrier }"/> + targetRegions="{ wellRegion1, wellRegion2 }" + writeCSV="1"> + logLevel="1" + type="producer"> + + + + surfacePressure="101325"> + + + - - + minTime="-1e11" + maxTime="1e7"> - + + - + - @@ -118,24 +124,25 @@ name="linearElasticityStatistics" solidSolverName="linearElasticity" logLevel="1"/> + - - + + - diff --git a/inputFiles/poromechanicsFractures/singlePhasePoromechanics_FaultModel_well_fim_new_smoke.xml b/inputFiles/poromechanicsFractures/singlePhasePoromechanics_FaultModel_well_fim_new_smoke.xml index 07a6e1521ff..ab10b0681c3 100644 --- a/inputFiles/poromechanicsFractures/singlePhasePoromechanics_FaultModel_well_fim_new_smoke.xml +++ b/inputFiles/poromechanicsFractures/singlePhasePoromechanics_FaultModel_well_fim_new_smoke.xml @@ -1,14 +1,16 @@ + + - + - + solverType="direct"/> - + logLevel="1"/> + targetRegions="{ Region, Fault }" + discretization="FE1"/> - + targetRegions="{ Region, Fault }"/> + targetRegions="{ wellRegion1, wellRegion2 }" + writeCSV="1"> + type="producer"> + + + + type="injector"> + + + - + + - - - + - + - + solverType="direct"/> - + logLevel="1"/> + targetRegions="{ Region, Fault }" + discretization="FE1"/> - + targetRegions="{ Region, Fault }"/> + targetRegions="{ wellRegion1, wellRegion2 }" + writeCSV="1"> + type="producer"> + + + + type="injector"> + + + - + + - - - + - + - + solverType="direct"/> + targetRegions="{ Region, Fault }" + discretization="FE1"/> - + targetRegions="{ Region, Fault }"/> + targetRegions="{ wellRegion1, wellRegion2 }" + writeCSV="1"> + type="producer"> + + + + type="injector"> + + + - + + - - - + - + - + solverType="direct"/> + targetRegions="{ Region, Fault }" + discretization="FE1"/> - + targetRegions="{ Region, Fault }"/> + targetRegions="{ wellRegion1, wellRegion2 }" + writeCSV="1"> + type="producer"> + + + + type="injector"> + + + - + + - - - + targetRegions="{ region , wellRegion2 }"> - + targetRegions="{ region }"/> + targetRegions="{ wellRegion2 }" + writeCSV="1"> + surfaceTemperature="300.15"> + + + @@ -78,13 +82,13 @@ name="region" cellBlocks="{ * }" materialList="{ fluid, rock, thermalCond }"/> + - - - - diff --git a/inputFiles/singlePhaseWell/compressible_single_phase_wells_1d.xml b/inputFiles/singlePhaseWell/compressible_single_phase_wells_1d.xml index 4b5f64d0287..f00f069df6c 100644 --- a/inputFiles/singlePhaseWell/compressible_single_phase_wells_1d.xml +++ b/inputFiles/singlePhaseWell/compressible_single_phase_wells_1d.xml @@ -23,21 +23,30 @@ + targetRegions="{ wellRegion1, wellRegion2 }" + writeCSV="1"> + type="producer"> + + + + type="injector"> + + + @@ -52,7 +61,6 @@ ny="{ 1 }" nz="{ 1 }" cellBlockNames="{ cb1 }"> - - + targetRegions="{ wellRegion1, wellRegion2 }" + writeCSV="1"> + type="producer"> + + + + type="injector"> + + + @@ -52,7 +61,6 @@ ny="{ 1 }" nz="{ 1 }" cellBlockNames="{ cb1 }"> - + distanceFromHead="1.45" + skinFactor="1"/> - + targetRegions="{ wellRegion1, wellRegion2 }" + writeCSV="1"> + type="producer"> + + + + type="injector"> + + + @@ -53,7 +62,6 @@ ny="{ 1 }" nz="{ 1 }" cellBlockNames="{ cb1 }"> - - + targetRegions="{ wellRegion1, wellRegion2, wellRegion3 }" + writeCSV="1"> + type="producer"> + + + + type="producer"> + + + + initialPressureCoefficient="0.01"> + + + @@ -60,7 +73,6 @@ ny="{ 20 }" nz="{ 1 }" cellBlockNames="{ cb1 }"> - - - + name="singlePhaseTPFA"/> diff --git a/inputFiles/singlePhaseWell/incompressible_single_phase_wells_hybrid_2d.xml b/inputFiles/singlePhaseWell/incompressible_single_phase_wells_hybrid_2d.xml index 743a1f7be70..713148d0623 100644 --- a/inputFiles/singlePhaseWell/incompressible_single_phase_wells_hybrid_2d.xml +++ b/inputFiles/singlePhaseWell/incompressible_single_phase_wells_hybrid_2d.xml @@ -24,28 +24,41 @@ + targetRegions="{ wellRegion1, wellRegion2, wellRegion3 }" + writeCSV="1"> + type="producer"> + + + + type="producer"> + + + + type="injector"> + + + @@ -60,7 +73,6 @@ ny="{ 20 }" nz="{ 1 }" cellBlockNames="{ cb1 }"> - - - + targetRegions="{ wellRegion1, wellRegion2, wellRegion3 }"> + type="producer"> + + + + type="producer"> + + + + initialPressureCoefficient="0.01"> + + + @@ -62,7 +74,6 @@ ny="{ 20 }" nz="{ 1 }" cellBlockNames="{ cb1 }"> - - - + name="singlePhaseTPFA"/> diff --git a/inputFiles/singlePhaseWell/staircase_single_phase_wells_3d.xml b/inputFiles/singlePhaseWell/staircase_single_phase_wells_3d.xml index 6789ab90542..f5f13ff1a8f 100644 --- a/inputFiles/singlePhaseWell/staircase_single_phase_wells_3d.xml +++ b/inputFiles/singlePhaseWell/staircase_single_phase_wells_3d.xml @@ -16,28 +16,37 @@ + targetRegions="{ wellRegion1, wellRegion2 }" + writeCSV="1"> + type="producer"> + + + + type="injector"> + + + @@ -51,11 +60,7 @@ nx="{ 5, 5 }" ny="{ 5, 5 }" nz="{ 3, 3, 3, 3 }" - cellBlockNames="{ cb-0_0_0, cb-1_0_0, cb-0_1_0, cb-1_1_0, - cb-0_0_1, cb-1_0_1, cb-0_1_1, cb-1_1_1, - cb-0_0_2, cb-1_0_2, cb-0_1_2, cb-1_1_2, - cb-0_0_3, cb-1_0_3, cb-0_1_3, cb-1_1_3 }"> - + cellBlockNames="{ cb-0_0_0, cb-1_0_0, cb-0_1_0, cb-1_1_0, cb-0_0_1, cb-1_0_1, cb-0_1_1, cb-1_1_1, cb-0_0_2, cb-1_0_2, cb-0_1_2, cb-1_1_2, cb-0_0_3, cb-1_0_3, cb-0_1_3, cb-1_1_3 }"> - @@ -172,9 +176,9 @@ diff --git a/inputFiles/singlePhaseWell/staircase_single_phase_wells_hybrid_3d.xml b/inputFiles/singlePhaseWell/staircase_single_phase_wells_hybrid_3d.xml index 2298a32e483..75917089291 100644 --- a/inputFiles/singlePhaseWell/staircase_single_phase_wells_hybrid_3d.xml +++ b/inputFiles/singlePhaseWell/staircase_single_phase_wells_hybrid_3d.xml @@ -24,23 +24,32 @@ + targetRegions="{ wellRegion1, wellRegion2 }" + writeCSV="1"> + type="producer"> + + + + surfacePressure="101325"> + + + @@ -54,11 +63,7 @@ nx="{ 5, 5 }" ny="{ 5, 5 }" nz="{ 3, 3, 3, 3 }" - cellBlockNames="{ cb-0_0_0, cb-1_0_0, cb-0_1_0, cb-1_1_0, - cb-0_0_1, cb-1_0_1, cb-0_1_1, cb-1_1_1, - cb-0_0_2, cb-1_0_2, cb-0_1_2, cb-1_1_2, - cb-0_0_3, cb-1_0_3, cb-0_1_3, cb-1_1_3 }"> - + cellBlockNames="{ cb-0_0_0, cb-1_0_0, cb-0_1_0, cb-1_1_0, cb-0_0_1, cb-1_0_1, cb-0_1_1, cb-1_1_1, cb-0_0_2, cb-1_0_2, cb-0_1_2, cb-1_1_2, cb-0_0_3, cb-1_0_3, cb-0_1_3, cb-1_1_3 }"> - (no description available)--> - + @@ -1518,7 +1518,7 @@ - + From 8b21d69083e7e89fb2e0d46baab6e02aec1eb4bf Mon Sep 17 00:00:00 2001 From: Thomas James Byer Date: Tue, 28 Oct 2025 07:48:23 -0700 Subject: [PATCH 18/71] remove extra ; --- .../fluidFlow/wells/WellPhaseVolumeRateConstraint.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.hpp index a98daba827e..bb7880cfc0c 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.hpp @@ -44,7 +44,7 @@ localIndex getPhaseIndexFromFluidModel( T const & fluidModel, std::string const } } return phaseIndex; -}; +} /** * @class PhaseVolumeRateConstraint From 470a7ff7198e2088e36cf0957cb36fa5fd3ec8a9 Mon Sep 17 00:00:00 2001 From: Thomas James Byer Date: Tue, 28 Oct 2025 10:48:00 -0700 Subject: [PATCH 19/71] remove : --- .../physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index 98d91cca41f..c6c20c35e4b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -603,7 +603,7 @@ void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh } -}; +} void SinglePhaseWell::initializeWells( DomainPartition & domain, real64 const & time_n ) { GEOS_MARK_FUNCTION; From b8a90f45a2f7e50e6660e3a46356cf27a38e215c Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 28 Oct 2025 15:07:35 -0700 Subject: [PATCH 20/71] fix constraint schema, phase name on totalvol constraint not allowed --- .../dome_kvalue_base.xml | 658 ++++++++++-------- .../dome_soreide_whitson_base.xml | 617 ++++++++-------- 2 files changed, 690 insertions(+), 585 deletions(-) diff --git a/inputFiles/compositionalMultiphaseWell/dome_kvalue_base.xml b/inputFiles/compositionalMultiphaseWell/dome_kvalue_base.xml index 305c01ce806..7e63134bde5 100644 --- a/inputFiles/compositionalMultiphaseWell/dome_kvalue_base.xml +++ b/inputFiles/compositionalMultiphaseWell/dome_kvalue_base.xml @@ -1,304 +1,360 @@ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inputFiles/compositionalMultiphaseWell/dome_soreide_whitson_base.xml b/inputFiles/compositionalMultiphaseWell/dome_soreide_whitson_base.xml index 2e00878f00e..4c124479e45 100644 --- a/inputFiles/compositionalMultiphaseWell/dome_soreide_whitson_base.xml +++ b/inputFiles/compositionalMultiphaseWell/dome_soreide_whitson_base.xml @@ -1,287 +1,336 @@ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 94fc9adc519112955c3ff94467b17623aaeced4a Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Wed, 29 Oct 2025 08:22:43 -0700 Subject: [PATCH 21/71] update well constraint schema --- ...eservoirCompositionalMultiphaseMSWells.cpp | 18 +++++--- ...eservoirCompositionalMultiphaseSSWells.cpp | 18 +++++--- .../wellsTests/testOpenClosePerf.cpp | 19 +++++--- ...eservoirCompositionalMultiphaseMSWells.cpp | 40 ++++++++++------- .../testReservoirSinglePhaseMSWells.cpp | 35 +++++++++------ ...testReservoirThermalSinglePhaseMSWells.cpp | 43 ++++++++++++------- ...rvoirThermalSinglePhaseMSWells_RateInj.cpp | 28 ++++++------ ...eservoirCompositionalMultiphaseMSWells.cpp | 18 +++++--- ...eservoirCompositionalMultiphaseSSWells.cpp | 18 +++++--- 9 files changed, 147 insertions(+), 90 deletions(-) diff --git a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp index da7d3606fb2..6fbde0a035a 100644 --- a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp @@ -103,16 +103,20 @@ char const * xmlInput = name="WC_CO2_INJ" logLevel="2" type="injector" - control="totalVolRate" - referenceElevation="-0.01" - targetBHP="1.45e7" enableCrossflow="0" useSurfaceConditions="1" surfacePressure="1.45e7" - surfaceTemperature="300.15" - targetTotalRate="0.001" - injectionTemperature="300.15" - injectionStream="{ 1.0, 0.0 }"/> + surfaceTemperature="300.15"> + + + diff --git a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp index 277c7a2a38c..bbfd13a4716 100644 --- a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp @@ -103,16 +103,20 @@ char const * xmlInput = name="WC_CO2_INJ" logLevel="2" type="injector" - control="totalVolRate" - referenceElevation="-0.01" - targetBHP="1.45e7" enableCrossflow="0" useSurfaceConditions="1" surfacePressure="1.45e7" - surfaceTemperature="300.15" - targetTotalRate="0.001" - injectionTemperature="300.15" - injectionStream="{ 1.0, 0.0 }"/> + surfaceTemperature="300.15"> + + + diff --git a/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp b/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp index c45c9a21e68..1ac7cbabbed 100644 --- a/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp @@ -61,13 +61,18 @@ char const * PreXmlInput = logLevel="1" targetRegions="{wellRegion1}" useMass="0"> - + + + + diff --git a/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp index f1ca32e9e81..aac23d23673 100644 --- a/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp @@ -61,21 +61,31 @@ char const * xmlInput = logLevel="1" targetRegions="{wellRegion1,wellRegion2}" useMass="0"> - - + + + + + + + + diff --git a/src/coreComponents/integrationTests/wellsTests/testReservoirSinglePhaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testReservoirSinglePhaseMSWells.cpp index d75ad50a957..fd213bb1431 100644 --- a/src/coreComponents/integrationTests/wellsTests/testReservoirSinglePhaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testReservoirSinglePhaseMSWells.cpp @@ -61,18 +61,29 @@ char const * PreXmlInput = - - + + + + + + + + + diff --git a/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells.cpp index d10f1da56f6..4faef42f2ca 100644 --- a/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells.cpp @@ -64,22 +64,33 @@ char const * PreXmlInput = logLevel="1" isThermal="1" targetRegions="{wellRegion1,wellRegion2}"> - - + + + + + + + + + diff --git a/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells_RateInj.cpp b/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells_RateInj.cpp index 255b0201692..521a9770227 100644 --- a/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells_RateInj.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells_RateInj.cpp @@ -79,19 +79,23 @@ char const * XmlInput = isThermal="1" writeCSV="1" targetRegions="{ wellRegion2 }"> - + + referenceElevation="-0.01"/> + + diff --git a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp index 98aa57a5c84..2795db9e5ff 100644 --- a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp @@ -107,16 +107,20 @@ char const * xmlInput = name="WC_CO2_INJ" logLevel="2" type="injector" - control="totalVolRate" - referenceElevation="-0.01" - targetBHP="1.45e7" enableCrossflow="0" useSurfaceConditions="1" surfacePressure="1.45e7" - surfaceTemperature="300.15" - targetTotalRate="0.001" - injectionTemperature="300.15" - injectionStream="{ 0.99, 0.01 }"/> + surfaceTemperature="300.15"> + + + diff --git a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp index 76fa20d4cea..cd37e4f0343 100644 --- a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp @@ -108,16 +108,20 @@ char const * xmlInput = name="WC_CO2_INJ" logLevel="2" type="injector" - control="totalVolRate" - referenceElevation="-0.01" - targetBHP="1.45e7" enableCrossflow="0" useSurfaceConditions="1" surfacePressure="1.45e7" - surfaceTemperature="300.15" - targetTotalRate="0.001" - injectionTemperature="300.15" - injectionStream="{ 0.99, 0.01 }"/> + surfaceTemperature="300.15"> + + + From 17047bd321ac96b68da5cff6241c7f1f04f5c838 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Wed, 29 Oct 2025 11:20:59 -0700 Subject: [PATCH 22/71] 1) expose method for unit tests, 2) update unittests accordingly --- ...malReservoirCompositionalMultiphaseMSWells.cpp | 1 + ...malReservoirCompositionalMultiphaseSSWells.cpp | 2 +- ...estReservoirCompositionalMultiphaseMSWells.cpp | 1 + .../testReservoirSinglePhaseMSWells.cpp | 2 ++ .../testReservoirThermalSinglePhaseMSWells.cpp | 1 + ...ReservoirThermalSinglePhaseMSWells_RateInj.cpp | 2 ++ ...malReservoirCompositionalMultiphaseMSWells.cpp | 1 + ...malReservoirCompositionalMultiphaseSSWells.cpp | 1 + .../wells/CompositionalMultiphaseWell.hpp | 15 +++++++-------- .../fluidFlow/wells/SinglePhaseWell.hpp | 14 ++++++++------ .../fluidFlow/wells/WellSolverBase.hpp | 14 ++++++++------ 11 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp index 6fbde0a035a..ac9f3348e9c 100644 --- a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp @@ -584,6 +584,7 @@ class CompositionalMultiphaseReservoirSolverTest : public ::testing::Test solver->getSystemSolution() ); solver->implicitStepSetup( time, dt, domain ); + solver->wellSolver()->initializeWells( domain, time ); } static real64 constexpr time = 0.0; diff --git a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp index bbfd13a4716..2a0f6b3c916 100644 --- a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp @@ -535,7 +535,6 @@ void testNumericalJacobian( CompositionalMultiphaseReservoirAndWells< Compositio real64 const dP = perturbParameter * ( wellElemPressure[iwelem] + perturbParameter ); wellElemPressure.move( hostMemorySpace, true ); wellElemPressure[iwelem] += dP; - // after perturbing, update the pressure-dependent quantities in the well wellSolver.updateState( domain ); @@ -656,6 +655,7 @@ class CompositionalMultiphaseReservoirSolverTest : public ::testing::Test solver->getSystemSolution() ); solver->implicitStepSetup( time, dt, domain ); + solver->wellSolver()->initializeWells( domain, time ); } static real64 constexpr time = 0.0; diff --git a/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp index aac23d23673..3dae76cda75 100644 --- a/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp @@ -493,6 +493,7 @@ class CompositionalMultiphaseReservoirSolverTest : public ::testing::Test solver->getSystemSolution() ); solver->implicitStepSetup( time, dt, domain ); + solver->wellSolver()->initializeWells( domain, time ); } static real64 constexpr time = 0.0; diff --git a/src/coreComponents/integrationTests/wellsTests/testReservoirSinglePhaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testReservoirSinglePhaseMSWells.cpp index fd213bb1431..94fcac71de5 100644 --- a/src/coreComponents/integrationTests/wellsTests/testReservoirSinglePhaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testReservoirSinglePhaseMSWells.cpp @@ -368,6 +368,8 @@ class SinglePhaseReservoirSolverTest : public ::testing::Test solver->getSystemSolution() ); solver->implicitStepSetup( TIME, DT, domain ); + + solver->wellSolver()->initializeWells( domain, TIME ); } void TestAssembleCouplingTerms() diff --git a/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells.cpp index 4faef42f2ca..64b3e9ec31d 100644 --- a/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells.cpp @@ -526,6 +526,7 @@ class SinglePhaseReservoirSolverTest : public ::testing::Test solver->getSystemSolution() ); solver->implicitStepSetup( TIME, DT, domain ); + solver->wellSolver()->initializeWells( domain, TIME ); } void TestAssembleCouplingTerms() diff --git a/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells_RateInj.cpp b/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells_RateInj.cpp index 521a9770227..a81f1f14605 100644 --- a/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells_RateInj.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells_RateInj.cpp @@ -601,6 +601,8 @@ class SinglePhaseReservoirSolverTest : public ::testing::Test solver->getSystemSolution() ); solver->implicitStepSetup( TIME, DT, domain ); + + solver->wellSolver()->initializeWells( domain, TIME ); } void TestAssembleCouplingTerms() diff --git a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp index 2795db9e5ff..ec766fa8324 100644 --- a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp @@ -703,6 +703,7 @@ class CompositionalMultiphaseReservoirSolverTest : public ::testing::Test solver->getSystemSolution() ); solver->implicitStepSetup( time, dt, domain ); + solver->wellSolver()->initializeWells( domain, time ); } static real64 constexpr time = 0.0; diff --git a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp index cd37e4f0343..14f28e28b66 100644 --- a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp @@ -692,6 +692,7 @@ class CompositionalMultiphaseReservoirSolverTest : public ::testing::Test solver->getSystemSolution() ); solver->implicitStepSetup( time, dt, domain ); + solver->wellSolver()->initializeWells( domain, time ); } static real64 constexpr time = 0.0; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp index 6a8998fca4f..13c83d12539 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp @@ -336,6 +336,13 @@ class CompositionalMultiphaseWell : public WellSolverBase void chopNegativeDensities( WellElementSubRegion & subRegion ); + /** + * @brief Initialize all the primary and secondary variables in all the wells + * @param domain the domain containing the well manager to access individual wells + */ + void initializeWells( DomainPartition & domain, real64 const & time_n ) override; + void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) override; + struct viewKeyStruct : WellSolverBase::viewKeyStruct { static constexpr char const * dofFieldString() { return "compositionalWellVars"; } @@ -445,14 +452,6 @@ class CompositionalMultiphaseWell : public WellSolverBase private: - /** - * @brief Initialize all the primary and secondary variables in all the wells - * @param domain the domain containing the well manager to access individual wells - */ - void initializeWells( DomainPartition & domain, real64 const & time_n ) override; - - void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) override; - virtual void setConstitutiveNames( ElementSubRegionBase & subRegion ) const override; template< typename ... GROUPTYPES > diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp index b9294056d26..fc3b259bc95 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp @@ -317,6 +317,13 @@ class SinglePhaseWell : public WellSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) override; + /** + * @brief Initialize all the primary and secondary variables in all the wells + * @param domain the domain containing the well manager to access individual wells + */ + void initializeWells( DomainPartition & domain, real64 const & time_n ) override; + void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) override; + /* * @brief apply a special treatment to the wells that are shut * @param time_n the time at the previous converged time step @@ -358,12 +365,7 @@ class SinglePhaseWell : public WellSolverBase virtual void setConstitutiveNames( ElementSubRegionBase & subRegion ) const override; - /** - * @brief Initialize all the primary and secondary variables in all the wells - * @param domain the domain containing the well manager to access individual wells - */ - void initializeWells( DomainPartition & domain, real64 const & time_n ) override; - void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) override; + /** * @brief Make sure that the well constraints are compatible * @param time_n the time at the beginning of the time step diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp index 3f8bc66d6a5..ae1ff3194db 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp @@ -279,6 +279,13 @@ class WellSolverBase : public PhysicsSolverBase virtual real64 updateWellState( WellElementSubRegion & subRegion ) = 0; virtual void updateState( DomainPartition & domain ) override; + /** + * @brief Initialize all the primary and secondary variables in all the wells + * @param domain the domain containing the well manager to access individual wells + */ + virtual void initializeWells( DomainPartition & domain, real64 const & time_n ) = 0; + virtual void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) = 0; + /** * @brief Recompute all dependent quantities from primary variables (including constitutive * models) @@ -410,12 +417,7 @@ class WellSolverBase : public PhysicsSolverBase virtual void initializePostSubGroups() override; - /** - * @brief Initialize all the primary and secondary variables in all the wells - * @param domain the domain containing the well manager to access individual wells - */ - virtual void initializeWells( DomainPartition & domain, real64 const & time_n ) = 0; - virtual void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) = 0; + /** * @brief Make sure that the well constraints are compatible * @param time_n the time at the beginning of the time step From c6a349f095b804f1691225edd1797add6f715181 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Wed, 29 Oct 2025 13:09:11 -0700 Subject: [PATCH 23/71] schema change --- .../testTableFunctionsOutput.cpp | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/coreComponents/integrationTests/tableFunctionsFileTests/testTableFunctionsOutput.cpp b/src/coreComponents/integrationTests/tableFunctionsFileTests/testTableFunctionsOutput.cpp index bbb29ff0972..0aaea58d21c 100644 --- a/src/coreComponents/integrationTests/tableFunctionsFileTests/testTableFunctionsOutput.cpp +++ b/src/coreComponents/integrationTests/tableFunctionsFileTests/testTableFunctionsOutput.cpp @@ -89,20 +89,24 @@ char const * xmlInput = targetRegions="{ injwell }" logLevel="1" useMass="1"> - + + referenceElevation="-0.01"/> + + From 1c0322050628e2cbd0b0004e95e10836468314c3 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Wed, 29 Oct 2025 16:11:47 -0700 Subject: [PATCH 24/71] 1) remove unused vars , add missing constriant type in selector --- .../wells/CompositionalMultiphaseWell.cpp | 61 ++++--------------- .../wells/CompositionalMultiphaseWell.hpp | 19 ------ .../fluidFlow/wells/WellControls.cpp | 4 +- 3 files changed, 13 insertions(+), 71 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index defb9f36a3d..355cdf952ce 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -247,24 +247,13 @@ void CompositionalMultiphaseWell::registerDataOnMesh( Group & meshBodies ) WellControls & wellControls = getWellControls( subRegion ); wellControls.registerWrapper< real64 >( viewKeyStruct::currentBHPString() ); - wellControls.registerWrapper< array1d< real64 > >( viewKeyStruct::dCurrentBHPString() ). - setSizedFromParent( 0 ). - reference().resizeDimension< 0 >( m_numComponents + 2 ); // dP, dT, dC - wellControls.registerWrapper< array1d< real64 > >( viewKeyStruct::currentPhaseVolRateString() ). setSizedFromParent( 0 ). reference().resizeDimension< 0 >( m_numPhases ); - wellControls.registerWrapper< array2d< real64 > >( viewKeyStruct::dCurrentPhaseVolRateString() ). - setSizedFromParent( 0 ). - reference().resizeDimension< 0, 1 >( m_numPhases, m_numComponents + 3 ); // dP, dT, dC, dQ - wellControls.registerWrapper< real64 >( viewKeyStruct::massDensityString() ); wellControls.registerWrapper< real64 >( viewKeyStruct::currentTotalVolRateString() ); - wellControls.registerWrapper< array1d< real64 > >( viewKeyStruct::dCurrentTotalVolRateString() ). - setSizedFromParent( 0 ). - reference().resizeDimension< 0 >( m_numComponents + 3 ); // dP, dT, dC dQ wellControls.registerWrapper< real64 >( viewKeyStruct::massDensityString() ); @@ -535,63 +524,35 @@ void CompositionalMultiphaseWell::updateBHPForConstraint( WellElementSubRegion & { return; } - using Deriv = constitutive::multifluid::DerivativeOffset; - integer const numComp = m_numComponents; localIndex const iwelemRef = subRegion.getTopWellElementIndex(); - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); - integer const isThermal = fluid.isThermal(); // subRegion data - arrayView1d< real64 const > const & pres = subRegion.getField< well::pressure >(); - arrayView1d< real64 > const & totalMassDens = subRegion.getField< well::totalMassDensity >(); - arrayView2d< real64, compflow::USD_FLUID_DC > const & dTotalMassDens = subRegion.getField< well::dTotalMassDensity >(); - arrayView1d< real64 const > const wellElemGravCoef = subRegion.getField< well::gravityCoefficient >(); // control data - WellControls & wellControls = getWellControls( subRegion ); string const wellControlsName = wellControls.getName(); real64 const & refGravCoef = wellControls.getReferenceGravityCoef(); real64 & currentBHP = wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() ); - arrayView1d< real64 > const & dCurrentBHP = - wellControls.getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::dCurrentBHPString() ); - geos::internal::kernelLaunchSelectorCompThermSwitch( numComp, isThermal, [&] ( auto NC, auto ISTHERMAL ) - { - integer constexpr IS_THERMAL = ISTHERMAL(); - GEOS_UNUSED_VAR( NC ); - // bring everything back to host, capture the scalars by reference - forAll< serialPolicy >( 1, [&numComp, - pres, - totalMassDens, - dTotalMassDens, - wellElemGravCoef, - ¤tBHP, - &dCurrentBHP, - &iwelemRef, - &refGravCoef] ( localIndex const ) - { - real64 const diffGravCoef = refGravCoef - wellElemGravCoef[iwelemRef]; - currentBHP = pres[iwelemRef] + totalMassDens[iwelemRef] * diffGravCoef; - dCurrentBHP[Deriv::dP] = 1 + dTotalMassDens[iwelemRef][Deriv::dP] * diffGravCoef; - for( integer ic = 0; ic < numComp; ++ic ) - { - dCurrentBHP[Deriv::dC+ic] = dTotalMassDens[iwelemRef][Deriv::dC+ic] * diffGravCoef; - } - if constexpr ( IS_THERMAL ) - { - dCurrentBHP[Deriv::dT] = dTotalMassDens[iwelemRef][Deriv::dT] * diffGravCoef; - } - } ); + // bring everything back to host, capture the scalars by reference + forAll< serialPolicy >( 1, [ pres, + totalMassDens, + wellElemGravCoef, + ¤tBHP, + &iwelemRef, + &refGravCoef] ( localIndex const ) + { + real64 const diffGravCoef = refGravCoef - wellElemGravCoef[iwelemRef]; + currentBHP = pres[iwelemRef] + totalMassDens[iwelemRef] * diffGravCoef; } ); + GEOS_LOG_LEVEL_BY_RANK( logInfo::BoundaryConditions, GEOS_FMT( "{}: BHP (at the specified reference elevation) = {} Pa", wellControlsName, currentBHP ) ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp index 13c83d12539..23b39915b21 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp @@ -370,32 +370,13 @@ class CompositionalMultiphaseWell : public WellSolverBase static constexpr char const * massDensityString() { return "massDensity";} static constexpr char const * currentBHPString() { return "currentBHP"; } - static constexpr char const * dCurrentBHPString() { return "dCurrentBHP"; } - - static constexpr char const * dCurrentBHP_dPresString() { return "dCurrentBHP_dPres"; } - static constexpr char const * dCurrentBHP_dCompDensString() { return "dCurrentBHP_dCompDens"; } static constexpr char const * currentPhaseVolRateString() { return "currentPhaseVolumetricRate"; } - static constexpr char const * dCurrentPhaseVolRateString() { return "dCurrentPhaseVolumetricRate"; } - - - static constexpr char const * dCurrentPhaseVolRate_dPresString() { return "dCurrentPhaseVolumetricRate_dPres"; } - - static constexpr char const * dCurrentPhaseVolRate_dCompDensString() { return "dCurrentPhaseVolumetricRate_dCompDens"; } - - static constexpr char const * dCurrentPhaseVolRate_dRateString() { return "dCurrentPhaseVolumetricRate_dRate"; } 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"; } - - static constexpr char const * dCurrentTotalVolRate_dRateString() { return "dCurrentTotalVolumetricRate_dRate"; } - } viewKeysCompMultiphaseWell; protected: diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index 6020aaedf33..8826ec4b61d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -368,7 +368,7 @@ real64 WellControls::getTargetBHP( real64 const & targetTime ) const real64 WellControls::getInjectionTemperature() const { real64 injectionTemperature = 0.0; - this->forInjectionConstraints< InjectionConstraint< PhaseVolumeRateConstraint >, InjectionConstraint< VolumeRateConstraint > >( [&] ( auto & constraint ) + this->forInjectionConstraints< InjectionConstraint< PhaseVolumeRateConstraint >, InjectionConstraint< VolumeRateConstraint >, InjectionConstraint< MassRateConstraint > >( [&] ( auto & constraint ) { if( constraint.isConstraintActive()) { @@ -383,7 +383,7 @@ real64 WellControls::getInjectionTemperature() const arrayView1d< real64 const > WellControls::getInjectionStream() const { arrayView1d< real64 const > injectionStream; - forInjectionConstraints< InjectionConstraint< PhaseVolumeRateConstraint >, InjectionConstraint< VolumeRateConstraint > >( [&] ( auto & constraint ) + forInjectionConstraints< InjectionConstraint< PhaseVolumeRateConstraint >, InjectionConstraint< VolumeRateConstraint >, InjectionConstraint< MassRateConstraint > >( [&] ( auto & constraint ) { if( constraint.isConstraintActive() ) { From b5f6c5d828b6183b07b3dec86ffeab7d01ff9ac2 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Thu, 30 Oct 2025 13:13:58 -0700 Subject: [PATCH 25/71] reintroduce control keyword option to be consistent with previous in well initialization vagaries assoiated with useSurfaceConditions=0 --- .../wells/CompositionalMultiphaseWell.cpp | 52 +++++++++++-------- .../fluidFlow/wells/WellControls.cpp | 31 ++++++++++- .../fluidFlow/wells/WellControls.hpp | 14 ++++- 3 files changed, 72 insertions(+), 25 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 355cdf952ce..9c54601687f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -1056,32 +1056,35 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh if( time_n <= 0.0 || ( wellControls.isWellOpen( ) && !hasNonZeroRate ) ) { - // GEOS_LOG_RANK( "tjb initialize wells "<< subRegion.getName()); - if( !wellControls.getWellState() && isThermal() ) // tjb add as schema option - { - m_nextDt=43200; - } wellControls.setWellState( true ); if( wellControls.getCurrentConstraint() == nullptr ) { + // tjb needed for backward compatibility. and these 2 lists must be consistent + ConstraintTypeId inputControl = ConstraintTypeId(wellControls.getInputControl()); if( wellControls.isProducer() ) { - wellControls.forSubGroups< MinimumBHPConstraint >( [&]( auto & constraint ) - //wellControls.forSubGroups< PhaseProductionConstraint >( [&]( auto & constraint - // ) + wellControls.forSubGroups< MinimumBHPConstraint, ProductionConstraint< VolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, + ProductionConstraint< PhaseVolumeRateConstraint > >( [&]( auto & constraint ) { - wellControls.setCurrentConstraint( &constraint ); - wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old + if( constraint.getControl() == inputControl ) + { + wellControls.setCurrentConstraint( &constraint ); + wellControls.setControl( static_cast< WellControls::Control >(inputControl) ); // tjb old + } + } ); } else { - // tjb needed for backward compatibility - //wellControls.forSubGroups< MaximumBHPConstraint >( [&]( auto & constraint ) - wellControls.forSubGroups< InjectionConstraint< VolumeRateConstraint > >( [&]( auto & constraint ) + + wellControls.forSubGroups< MaximumBHPConstraint, InjectionConstraint< VolumeRateConstraint >, InjectionConstraint< MassRateConstraint >, + InjectionConstraint< PhaseVolumeRateConstraint > >( [&]( auto & constraint ) { - wellControls.setCurrentConstraint( &constraint ); - wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old + if( constraint.getControl() == inputControl ) + { + wellControls.setCurrentConstraint( &constraint ); + wellControls.setControl( static_cast< WellControls::Control >(inputControl) ); // tjb old + } } ); } } @@ -1451,13 +1454,13 @@ CompositionalMultiphaseWell::calculateWellResidualNorm( real64 const & time_n, arrayView1d< real64 const > const & localRhs ) { GEOS_MARK_FUNCTION; - integer numNorm = 1; // mass balance + integer numNorm = 1; // mass balance array1d< real64 > localResidualNorm; array1d< real64 > localResidualNormalizer; if( isThermal() ) { - numNorm = 2; // mass balance and energy balance + numNorm = 2; // mass balance and energy balance } localResidualNorm.resize( numNorm ); localResidualNormalizer.resize( numNorm ); @@ -2332,7 +2335,8 @@ void CompositionalMultiphaseWell::chopNegativeDensities( WellElementSubRegion & { if( iwelem == 65 ) { - std::cout << "tjb dens " << iwelem << " " << ic << " " << wellElemCompDens[iwelem][ic] << " " << wellElemCompDens_n[iwelem][ic] << + std::cout << "tjb dens " << iwelem << " " << ic << " " << wellElemCompDens[iwelem][ic] << " " << + wellElemCompDens_n[iwelem][ic] << std::endl; } } @@ -2922,7 +2926,8 @@ bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); constraint->setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), - " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << limitingConstraint->phaseVolumeRates() << " " << + " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << + limitingConstraint->phaseVolumeRates() << " " << limitingConstraint->totalVolumeRate() << " " << limitingConstraint->massRate()); } } @@ -2934,10 +2939,12 @@ bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, if( limitingConstraint->getName() != constraint->getName()) { - //std::cout << "Use estimator " << useEstimator << " Evaluating constraint " << constraint.getName() << " against constraint " << + //std::cout << "Use estimator " << useEstimator << " Evaluating constraint " << constraint.getName() << " against constraint " + // << // limitingConstraint->getName() << std::endl; if( constraint->checkViolation( *limitingConstraint, time_n ) ) { + limitingConstraint = constraint; wellControls.setControl( static_cast< WellControls::Control >(constraint->getControl()) ); // tjb old wellControls.setCurrentConstraint( constraint ); GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), @@ -2946,10 +2953,11 @@ bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, } } GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), - " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << limitingConstraint->phaseVolumeRates() << " " << + " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << + limitingConstraint->phaseVolumeRates() << " " << limitingConstraint->totalVolumeRate() << " " << limitingConstraint->massRate()); return true; } REGISTER_CATALOG_ENTRY( PhysicsSolverBase, CompositionalMultiphaseWell, string const &, Group * const ) -} // namespace geos +} // namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index 8826ec4b61d..abd8e434371 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -32,6 +32,7 @@ using namespace dataRepository; WellControls::WellControls( string const & name, Group * const parent ) : Group( name, parent ), m_type( Type::PRODUCER ), + m_inputControl( Control::UNINITIALIZED ), m_currentControl( Control::UNINITIALIZED ), // tjb remove m_useSurfaceConditions( 0 ), m_surfacePres( -1.0 ), @@ -57,7 +58,9 @@ WellControls::WellControls( string const & name, Group * const parent ) setInputFlag( InputFlags::FALSE ). setDescription( "Current well control" ); - + registerWrapper( viewKeyStruct::inputControlString(), &m_inputControl ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Well control. Valid options:\n* " + EnumStrings< Control >::concat( "\n* " ) ); registerWrapper( viewKeyStruct::useSurfaceConditionsString(), &m_useSurfaceConditions ). setDefaultValue( 0 ). @@ -208,6 +211,20 @@ TableFunction * createWellTable( string const & tableName, void WellControls::postInputInitialization() { + // 0) Assign the value of the current well control + // When the simulation starts from a restart file, we don't want to use the inputControl, + // because the control may have switched in the simulation that generated the restart + GEOS_THROW_IF( m_inputControl == Control::UNINITIALIZED, + getWrapperDataContext( viewKeyStruct::inputControlString() ) << + ": Input well control cannot be uninitialized", + InputError ); + + if( m_currentControl == Control::UNINITIALIZED ) + { + m_currentControl = m_inputControl; + } + + // 3) check the flag for surface / reservoir conditions GEOS_THROW_IF( m_useSurfaceConditions != 0 && m_useSurfaceConditions != 1, getWrapperDataContext( viewKeyStruct::useSurfaceConditionsString() ) << ": The flag to select surface/reservoir conditions must be equal to 0 or 1", @@ -229,7 +246,19 @@ void WellControls::postInputInitialization() ": This tuning coefficient is negative", InputError ); + // 6.2) Check incoherent information + // An injector must be controlled by TotalVolRate + GEOS_THROW_IF( (isInjector() && (m_inputControl == Control::PHASEVOLRATE)), + "WellControls " << getDataContext() << ": You have to control an injector with " + << EnumStrings< Control >::toString( Control::TOTALVOLRATE ), + InputError ); + + // An injector must be controlled by TotalVolRate + GEOS_THROW_IF( (isProducer() && (m_inputControl == Control::MASSRATE)), + "WellControls " << getDataContext() << ": You have to control an injector with " + << EnumStrings< Control >::toString( Control::MASSRATE ), + InputError ); // 12) Create the time-dependent well status table if( m_statusTableName.empty()) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp index 2bcb9aa6332..22218827d9a 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp @@ -267,6 +267,13 @@ class WellControls : public dataRepository::Group */ void setControl( Control const & newControl ) { m_currentControl = newControl; } + /** + * @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 gravity coefficient * @return the reference gravity coefficient @@ -453,10 +460,10 @@ class WellControls : public dataRepository::Group static constexpr char const * refElevString() { return "referenceElevation"; } /// String key for the well type static constexpr char const * typeString() { return "type"; } - /// String key for the well current control static constexpr char const * currentControlString() { return "currentControl"; } - + /// String key for the well input control + static constexpr char const * inputControlString() { return "control"; } /// String key for checking the rates at surface conditions static constexpr char const * useSurfaceConditionsString() { return "useSurfaceConditions"; } /// String key for reference reservoir region @@ -538,6 +545,9 @@ class WellControls : public dataRepository::Group /// Gravity coefficient of the reference elevation real64 m_refGravCoef; + /// Input well controls as a Control enum + Control m_inputControl; + /// Well controls as a Control enum Control m_currentControl; From c43657e10921f4fa48342a4378d46597e201e33c Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Thu, 30 Oct 2025 14:26:59 -0700 Subject: [PATCH 26/71] updated schema --- src/coreComponents/schema/schema.xsd | 12 ++++++++++++ src/coreComponents/schema/schema.xsd.other | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/coreComponents/schema/schema.xsd b/src/coreComponents/schema/schema.xsd index 48b47f76c46..84f0496f9c3 100644 --- a/src/coreComponents/schema/schema.xsd +++ b/src/coreComponents/schema/schema.xsd @@ -3542,6 +3542,13 @@ When set to `all` output both convergence & iteration information to a csv.--> + + @@ -3677,6 +3684,11 @@ See note on referenceReservoirRegion for reservoir condition options--> + + + + + diff --git a/src/coreComponents/schema/schema.xsd.other b/src/coreComponents/schema/schema.xsd.other index 2db214f01a7..39117919d1c 100644 --- a/src/coreComponents/schema/schema.xsd.other +++ b/src/coreComponents/schema/schema.xsd.other @@ -512,7 +512,7 @@ - + @@ -1518,7 +1518,7 @@ - + From e78ef183f1f5b37569c01ed1b87da9e8383b4db1 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Thu, 30 Oct 2025 14:34:45 -0700 Subject: [PATCH 27/71] add back control keyword --- .../1D_100cells/1D_benchmark.xml | 10 +++-- .../soreideWhitson/1D_100cells/1D_smoke.xml | 10 +++-- .../class09_pb3_drainageOnly_direct_base.xml | 6 +-- ...lass09_pb3_drainageOnly_iterative_base.xml | 12 +++--- .../class09_pb3_hystRelperm_direct_base.xml | 6 +-- ...class09_pb3_hystRelperm_iterative_base.xml | 6 +-- .../benchmarks/Egg/deadOilEgg_base_direct.xml | 39 ++++++++++++------- .../Egg/deadOilEgg_base_iterative.xml | 39 ++++++++++++------- .../black_oil_wells_saturated_3d.xml | 9 +++-- .../black_oil_wells_saturated_3d_stone2.xml | 9 +++-- .../black_oil_wells_unsaturated_3d.xml | 9 +++-- .../black_oil_wells_unsaturated_3d_stone2.xml | 9 +++-- .../compositional_multiphase_wells_1d.xml | 9 +++-- .../compositional_multiphase_wells_2d.xml | 12 +++--- .../dead_oil_wells_2d.xml | 12 +++--- .../dead_oil_wells_hybrid_2d.xml | 12 +++--- .../isothm_mass_inj_table.xml | 4 +- .../isothm_vol_inj_table.xml | 4 +- .../simpleCo2InjTutorial_base.xml | 6 +-- .../staged_perf_base.xml | 4 +- .../staircase_co2_wells_3d.xml | 9 +++-- .../staircase_co2_wells_hybrid_3d.xml | 9 +++-- .../PoroElastic_staircase_co2_3d_fim.xml | 9 +++-- ...oroElastic_staircase_co2_3d_sequential.xml | 9 +++-- ...roElastic_staircase_singlephase_3d_fim.xml | 9 +++-- ...ic_staircase_singlephase_3d_sequential.xml | 9 +++-- ...echanics_FaultModel_well_fim_new_smoke.xml | 9 +++-- ...oromechanics_FaultModel_well_seq_smoke.xml | 9 +++-- .../thermalCompressibleWell_base.xml | 6 +-- .../compressible_single_phase_wells_1d.xml | 9 +++-- ...sible_single_phase_wells_1d_skinFactor.xml | 9 +++-- ...pressible_single_phase_wells_hybrid_1d.xml | 9 +++-- .../incompressible_single_phase_wells_2d.xml | 12 +++--- ...pressible_single_phase_wells_hybrid_2d.xml | 12 +++--- .../singlePhaseWell/perf_status_test.xml | 10 +++-- .../staircase_single_phase_wells_3d.xml | 9 +++-- ...staircase_single_phase_wells_hybrid_3d.xml | 9 +++-- 37 files changed, 221 insertions(+), 163 deletions(-) diff --git a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml index 7bb21f00c3b..1218d8156a2 100644 --- a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml +++ b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml @@ -37,7 +37,6 @@ maxRelativePressureChange="0.5" maxCompFractionChange="0.5" targetRegions="{ WATER.INJECTOR, GAS.INJECTOR, PRODUCER }" - writeCSV="1" timeStepFromTables="1" logLevel="1"> + logLevel="0" + control="totalVolRate"> @@ -68,7 +68,8 @@ surfacePressure="1.013250e+05" surfaceTemperature="288.71" enableCrossflow="0" - logLevel="0"> + logLevel="0" + control="totalVolRate"> @@ -88,7 +89,8 @@ useSurfaceConditions="0" surfacePressure="1.013250e+05" surfaceTemperature="288.71" - logLevel="0"> + logLevel="0" + control="BHP"> + logLevel="0" + control="totalVolRate"> @@ -68,7 +68,8 @@ surfacePressure="1.013250e+05" surfaceTemperature="288.71" enableCrossflow="0" - logLevel="0"> + logLevel="0" + control="totalVolRate"> @@ -88,7 +89,8 @@ useSurfaceConditions="0" surfacePressure="1.013250e+05" surfaceTemperature="288.71" - logLevel="0"> + logLevel="0" + control="BHP"> + useMass="1"> + surfaceTemperature="288.71" + control="totalVolRate"> + useMass="1"> + surfaceTemperature="288.71" + control="totalVolRate"> + surfaceTemperature="288.71" + control="massRate"> + surfaceTemperature="288.71" + control="massRate"> + useMass="1"> + surfaceTemperature="288.71" + control="totalVolRate"> + useMass="1"> + surfaceTemperature="288.71" + control="totalVolRate"> + useMass="1"> + type="producer" + control="BHP"> + type="producer" + control="BHP"> + type="producer" + control="BHP"> + type="producer" + control="BHP"> + type="injector" + control="totalVolRate"> + type="injector" + control="totalVolRate"> + type="injector" + control="totalVolRate"> + type="injector" + control="totalVolRate"> + type="injector" + control="totalVolRate"> + type="injector" + control="totalVolRate"> + type="injector" + control="totalVolRate"> + type="injector" + control="totalVolRate"> + useMass="1"> + type="producer" + control="BHP"> + type="producer" + control="BHP"> + type="producer" + control="BHP"> + type="producer" + control="BHP"> + type="injector" + control="totalVolRate"> + type="injector" + control="totalVolRate"> + type="injector" + control="totalVolRate"> + type="injector" + control="totalVolRate"> + type="injector" + control="totalVolRate"> + type="injector" + control="totalVolRate"> + type="injector" + control="totalVolRate"> + type="injector" + control="totalVolRate"> + useMass="1"> + type="producer" + control="BHP"> + type="injector" + control="BHP"> + useMass="1"> + type="producer" + control="BHP"> + type="injector" + control="BHP"> + useMass="1"> + type="producer" + control="BHP"> + type="injector" + control="BHP"> + useMass="1"> + type="producer" + control="BHP"> + type="injector" + control="BHP"> + targetRegions="{ wellRegion1, wellRegion2 }"> + type="producer" + control="BHP"> + type="injector" + control="totalVolRate"> + targetRegions="{ wellRegion1, wellRegion2, wellRegion3 }"> + type="producer" + control="BHP"> + type="producer" + control="phaseVolRate"> + type="injector" + control="totalVolRate"> + maxCompFractionChange="0.1"> + surfaceTemperature="297.15" + control="BHP"> + surfaceTemperature="297.15" + control="phaseVolRate"> + surfaceTemperature="297.15" + control="totalVolRate"> + maxCompFractionChange="0.1"> + surfaceTemperature="297.15" + control="BHP"> + surfaceTemperature="297.15" + control="BHP"> + surfaceTemperature="297.15" + control="totalVolRate"> + surfaceTemperature="300.15" + control="massRate"> + surfaceTemperature="300.15" + control="totalVolRate"> + useMass="1"> + surfaceTemperature="288.71" + control="totalVolRate"> + type="producer" + control="BHP"> + useMass="1"> + type="producer" + control="phaseVolRate"> + type="injector" + control="totalVolRate"> + useMass="1"> + type="producer" + control="BHP"> + type="injector" + control="totalVolRate"> + useMass="1"> + type="producer" + control="BHP"> + surfaceTemperature="288.71" + control="totalVolRate"> + useMass="1"> + type="producer" + control="BHP"> + surfaceTemperature="288.71" + control="totalVolRate"> + targetRegions="{ wellRegion1, wellRegion2 }"> + type="producer" + control="BHP"> + surfacePressure="101325" + control="totalVolRate"> + targetRegions="{ wellRegion1, wellRegion2 }"> + type="producer" + control="BHP"> + surfacePressure="101325" + control="totalVolRate"> + targetRegions="{ wellRegion1, wellRegion2 }"> + type="producer" + control="BHP"> + type="injector" + control="BHP"> + targetRegions="{ wellRegion1, wellRegion2 }"> + type="producer" + control="BHP"> + type="injector" + control="BHP"> + targetRegions="{ wellRegion2 }"> + surfaceTemperature="300.15" + control="BHP"> + targetRegions="{ wellRegion1, wellRegion2 }"> + type="producer" + control="BHP"> + type="injector" + control="totalVolRate"> + targetRegions="{ wellRegion1, wellRegion2 }"> + type="producer" + control="BHP"> + type="injector" + control="totalVolRate"> + targetRegions="{ wellRegion1, wellRegion2 }"> + type="producer" + control="BHP"> + type="injector" + control="totalVolRate"> + targetRegions="{ wellRegion1, wellRegion2, wellRegion3 }"> + type="producer" + control="BHP"> + type="producer" + control="BHP"> + initialPressureCoefficient="0.01" + control="totalVolRate"> + targetRegions="{ wellRegion1, wellRegion2, wellRegion3 }"> + type="producer" + control="BHP"> + type="producer" + control="BHP"> + type="injector" + control="totalVolRate"> + type="producer" + control="BHP"> + type="producer" + control="BHP"> + initialPressureCoefficient="0.01" + control="totalVolRate"> + targetRegions="{ wellRegion1, wellRegion2 }"> + type="producer" + control="totalVolRate"> + type="injector" + control="totalVolRate"> + targetRegions="{ wellRegion1, wellRegion2 }"> + type="producer" + control="BHP"> + surfacePressure="101325" + control="totalVolRate"> Date: Thu, 30 Oct 2025 14:49:51 -0700 Subject: [PATCH 28/71] add control schema to unit tests --- .../testIsothermalReservoirCompositionalMultiphaseMSWells.cpp | 1 + .../testIsothermalReservoirCompositionalMultiphaseSSWells.cpp | 1 + .../integrationTests/wellsTests/testOpenClosePerf.cpp | 1 + .../wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp | 2 ++ .../wellsTests/testReservoirSinglePhaseMSWells.cpp | 2 ++ .../wellsTests/testReservoirThermalSinglePhaseMSWells.cpp | 2 ++ .../testReservoirThermalSinglePhaseMSWells_RateInj.cpp | 1 + .../testThermalReservoirCompositionalMultiphaseMSWells.cpp | 1 + .../testThermalReservoirCompositionalMultiphaseSSWells.cpp | 1 + 9 files changed, 12 insertions(+) diff --git a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp index ac9f3348e9c..83cf41e02f6 100644 --- a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp @@ -103,6 +103,7 @@ char const * xmlInput = name="WC_CO2_INJ" logLevel="2" type="injector" + control="totalVolRate" enableCrossflow="0" useSurfaceConditions="1" surfacePressure="1.45e7" diff --git a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp index 2a0f6b3c916..bf01638a399 100644 --- a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp @@ -103,6 +103,7 @@ char const * xmlInput = name="WC_CO2_INJ" logLevel="2" type="injector" + control="totalVolRate" enableCrossflow="0" useSurfaceConditions="1" surfacePressure="1.45e7" diff --git a/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp b/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp index 1ac7cbabbed..654e96f2e05 100644 --- a/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp @@ -71,6 +71,7 @@ char const * PreXmlInput = diff --git a/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp index 3dae76cda75..d6cdb3a31e0 100644 --- a/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp @@ -65,6 +65,7 @@ char const * xmlInput = name="wellControls1" type="producer"> @@ -75,6 +76,7 @@ char const * xmlInput = diff --git a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp index ec766fa8324..bd711598535 100644 --- a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp @@ -107,6 +107,7 @@ char const * xmlInput = name="WC_CO2_INJ" logLevel="2" type="injector" + control="totalVolRate" enableCrossflow="0" useSurfaceConditions="1" surfacePressure="1.45e7" diff --git a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp index 14f28e28b66..055682b1863 100644 --- a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp @@ -108,6 +108,7 @@ char const * xmlInput = name="WC_CO2_INJ" logLevel="2" type="injector" + control="totalVolRate" enableCrossflow="0" useSurfaceConditions="1" surfacePressure="1.45e7" From a319e0e45c755a5cfa588fc86363b741e35548ab Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Thu, 30 Oct 2025 14:56:48 -0700 Subject: [PATCH 29/71] uncrustify should be automated --- .../fluidFlow/wells/CompositionalMultiphaseWell.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 9c54601687f..aaed2ca2932 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -1060,7 +1060,7 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh if( wellControls.getCurrentConstraint() == nullptr ) { // tjb needed for backward compatibility. and these 2 lists must be consistent - ConstraintTypeId inputControl = ConstraintTypeId(wellControls.getInputControl()); + ConstraintTypeId inputControl = ConstraintTypeId( wellControls.getInputControl()); if( wellControls.isProducer() ) { wellControls.forSubGroups< MinimumBHPConstraint, ProductionConstraint< VolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, From 9b9ccc2e1009c929304ff272c5683d926d90d0d2 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Fri, 31 Oct 2025 07:13:49 -0700 Subject: [PATCH 30/71] add control schema --- inputFiles/compositionalMultiphaseWell/dome_kvalue_base.xml | 3 +++ .../compositionalMultiphaseWell/dome_soreide_whitson_base.xml | 3 +++ .../singlePhasePoromechanics_WellInFault_fim_smoke.xml | 2 ++ .../singlePhasePoromechanics_WellInFault_seq_smoke.xml | 2 ++ 4 files changed, 10 insertions(+) diff --git a/inputFiles/compositionalMultiphaseWell/dome_kvalue_base.xml b/inputFiles/compositionalMultiphaseWell/dome_kvalue_base.xml index 7e63134bde5..ab90d4d13c0 100644 --- a/inputFiles/compositionalMultiphaseWell/dome_kvalue_base.xml +++ b/inputFiles/compositionalMultiphaseWell/dome_kvalue_base.xml @@ -52,6 +52,7 @@ logLevel="1"> Date: Sun, 2 Nov 2025 11:31:36 -0800 Subject: [PATCH 31/71] restart fix --- .../wells/CompositionalMultiphaseWell.cpp | 31 ++++++++++ .../fluidFlow/wells/SinglePhaseWell.cpp | 56 +++++++++++++++---- 2 files changed, 76 insertions(+), 11 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index aaed2ca2932..e376f0d33aa 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -1193,6 +1193,37 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh else { wellControls.setWellState( true ); + // setup if restart + if( wellControls.getCurrentConstraint() == nullptr ) + { + updateSubRegionState( subRegion ); + if( wellControls.isProducer() ) + { + wellControls.forSubGroups< MinimumBHPConstraint, ProductionConstraint< VolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, + ProductionConstraint< PhaseVolumeRateConstraint > >( [&]( + auto + & constraint ) + { + if( ConstraintTypeId( wellControls.getControl()) == constraint.getControl() ) + { + wellControls.setCurrentConstraint( &constraint ); + } + } ); + } + else + { + wellControls.forSubGroups< MaximumBHPConstraint, InjectionConstraint< VolumeRateConstraint >, InjectionConstraint< MassRateConstraint >, InjectionConstraint< PhaseVolumeRateConstraint > >( [&]( + auto + & + constraint ) + { + if( ConstraintTypeId( wellControls.getControl()) == constraint.getControl() ) + { + wellControls.setCurrentConstraint( &constraint ); + } + } ); + } + } } } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index c6c20c35e4b..85db057f562 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -520,23 +520,26 @@ void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh { if( wellControls.isProducer() ) { - wellControls.forSubGroups< MinimumBHPConstraint >( [&]( auto & constraint ) - //wellControls.forSubGroups< PhaseProductionConstraint >( [&]( auto & - // constraint - // ) + wellControls.forSubGroups< MinimumBHPConstraint, ProductionConstraint< VolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, + ProductionConstraint< PhaseVolumeRateConstraint > >( [&]( auto & constraint ) { - wellControls.setCurrentConstraint( &constraint ); - wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old + if( ConstraintTypeId( wellControls.getControl()) == constraint.getControl() ) + { + wellControls.setCurrentConstraint( &constraint ); + wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old + } } ); } else { - // tjb needed for backward compatibility - //wellControls.forSubGroups< MaximumBHPConstraint >( [&]( auto & constraint ) - wellControls.forSubGroups< InjectionConstraint< VolumeRateConstraint > >( [&]( auto & constraint ) + wellControls.forSubGroups< MaximumBHPConstraint, InjectionConstraint< VolumeRateConstraint >, InjectionConstraint< MassRateConstraint >, + InjectionConstraint< PhaseVolumeRateConstraint > >( [&]( auto & constraint ) { - wellControls.setCurrentConstraint( &constraint ); - wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old + if( ConstraintTypeId( wellControls.getControl()) == constraint.getControl() ) + { + wellControls.setCurrentConstraint( &constraint ); + wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old + } } ); } } @@ -600,6 +603,37 @@ void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh else { wellControls.setWellState( true ); + // setup for restart + if( wellControls.getCurrentConstraint() == nullptr ) + { + updateSubRegionState( subRegion ); + if( wellControls.isProducer() ) + { + wellControls.forSubGroups< MinimumBHPConstraint, ProductionConstraint< VolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, + ProductionConstraint< PhaseVolumeRateConstraint > >( [&]( + auto + & constraint ) + { + if( ConstraintTypeId( wellControls.getControl()) == constraint.getControl() ) + { + wellControls.setCurrentConstraint( &constraint ); + } + } ); + } + else + { + wellControls.forSubGroups< MaximumBHPConstraint, InjectionConstraint< VolumeRateConstraint >, InjectionConstraint< MassRateConstraint >, InjectionConstraint< PhaseVolumeRateConstraint > >( [&]( + auto + & + constraint ) + { + if( ConstraintTypeId( wellControls.getControl()) == constraint.getControl() ) + { + wellControls.setCurrentConstraint( &constraint ); + } + } ); + } + } } From 5116adbd12034cc1986f0a8f16b7e4bfb08dd327 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Mon, 3 Nov 2025 06:34:31 -0800 Subject: [PATCH 32/71] merge --- ...oromechanics_FaultModel_well_fim_smoke.xml | 216 +++++++++-------- ...oromechanics_FaultModel_well_seq_smoke.xml | 229 +++++++++--------- 2 files changed, 225 insertions(+), 220 deletions(-) diff --git a/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_fim_smoke.xml b/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_fim_smoke.xml index 0ce10628d75..c408db31a9d 100644 --- a/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_fim_smoke.xml +++ b/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_fim_smoke.xml @@ -1,134 +1,136 @@ - + + - - + gravityVector="{0.0, 0.0, -9.81}"> + name="reservoirSolver" + targetRegions="{Region, Fault}" + initialDt="3600" + reservoirAndWellsSolverName="reservoirAndWellsSolver" + solidSolverName="fractureMechSolver" + logLevel="3"> + couplingType="FullyImplicit" + lineSearchAction="None" + maxTimeStepCuts="10" + newtonTol="1e-2" + newtonMaxIter="20" + maxAllowedResidualNorm="1e+15"> + + directParallel="0"> + - - + name="fractureMechSolver" + stabilizationName="TPFA_stab" + logLevel="1" + targetRegions="{Region, Fault}" + discretization="FE1"> + - - - + name="reservoirAndWellsSolver" + flowSolverName="flowSolver" + wellSolverName="wellSolver" + targetRegions="{Region, Fault, wellInjector}" + logLevel="3"> + + + + name="wellSolver" + targetRegions="{wellInjector}" + useMass="1" + logLevel="2"> + name="injectorControls" + type="injector" + useSurfaceConditions="1" + surfacePressure="1.01325e6" + surfaceTemperature="367.15" + control="totalVolRate" + enableCrossflow="0" + logLevel="2"> + + + + + - + name="mesh1" + useGlobalIds="1" + faceBlocks="{fracture}" + file="verticalFault_ExternalMesh.vtm"> + name="well_injector" + logLevel="1" + wellRegionName="wellInjector" + wellControlsName="injectorControls" + polylineNodeCoords="{{-600, -600, -2000}, {-600, -600, -2500}}" + polylineSegmentConn="{{0, 1}}" + radius="0.1" + numElementsPerSegment="1"> + name="injector_perf1" + distanceFromHead="250"> + - + - - - - - + minTime="-1e11" + maxTime="111600"> + + - + name="outputPostEquilibrationStep1" + targetTime="0" + targetExactTimestep="1" + target="/Outputs/vtkOutput"> + - + name="solverApplication" + endTime="1.0e5" + maxEventDt="1.0e5" + target="/Solvers/reservoirSolver"> + - + name="outputs" + beginTime="0.0" + endTime="1.0e5" + timeFrequency="1.0e5" + target="/Outputs/vtkOutput"> + + name="restarts" + beginTime="0.0" + timeFrequency="1.0e5" + endTime="1.0e5" + target="/Outputs/restartOutput"> + diff --git a/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_seq_smoke.xml b/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_seq_smoke.xml index d0959438756..cf99b1875b4 100644 --- a/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_seq_smoke.xml +++ b/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_seq_smoke.xml @@ -1,143 +1,146 @@ - + + - - + gravityVector="{0.0, 0.0, -9.81}"> + name="reservoirSolver" + targetRegions="{Region, Fault}" + initialDt="3600" + reservoirAndWellsSolverName="reservoirAndWellsSolver" + solidSolverName="fractureMechSolver" + logLevel="3"> + couplingType="Sequential" + lineSearchAction="None" + maxTimeStepCuts="10" + newtonTol="1e-2" + newtonMaxIter="20" + maxAllowedResidualNorm="1e+15"> + + directParallel="0"> + - - + name="fractureMechSolver" + stabilizationName="TPFA_stab" + logLevel="1" + targetRegions="{Region, Fault}" + discretization="FE1"> + + name="reservoirAndWellsSolver" + flowSolverName="flowSolver" + wellSolverName="wellSolver" + targetRegions="{Region, Fault, wellInjector}" + logLevel="3"> + lineSearchAction="None" + maxTimeStepCuts="10" + newtonTol="1e-2" + newtonMaxIter="20"> + + solverType="fgmres" + preconditionerType="mgr"> + - - - + + + name="wellSolver" + targetRegions="{wellInjector}" + useMass="1" + logLevel="2"> + name="injectorControls" + type="injector" + useSurfaceConditions="1" + surfacePressure="1.01325e6" + surfaceTemperature="367.15" + control="totalVolRate" + enableCrossflow="0" + logLevel="2"> + + + + + - + name="mesh1" + useGlobalIds="1" + faceBlocks="{fracture}" + file="verticalFault_ExternalMesh.vtm"> + name="well_injector" + logLevel="1" + wellRegionName="wellInjector" + wellControlsName="injectorControls" + polylineNodeCoords="{{-600, -600, -2000}, {-600, -600, -2500}}" + polylineSegmentConn="{{0, 1}}" + radius="0.1" + numElementsPerSegment="1"> + name="injector_perf1" + distanceFromHead="250"> + - + - - - - - + minTime="-1e11" + maxTime="111600"> + + - + name="outputPostEquilibrationStep1" + targetTime="0" + targetExactTimestep="1" + target="/Outputs/vtkOutput"> + - + name="solverApplication" + endTime="1.0e5" + maxEventDt="1.0e5" + target="/Solvers/reservoirSolver"> + - + name="outputs" + beginTime="0.0" + endTime="1.0e5" + timeFrequency="1.0e5" + target="/Outputs/vtkOutput"> + + name="restarts" + beginTime="0.0" + timeFrequency="1.0e5" + endTime="1.0e5" + target="/Outputs/restartOutput"> + From bfde8cf18a10a757883163a31a6fb2ff7599188a Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Mon, 3 Nov 2025 06:50:56 -0800 Subject: [PATCH 33/71] Revert "merge" This reverts commit 5116adbd12034cc1986f0a8f16b7e4bfb08dd327. --- ...oromechanics_FaultModel_well_fim_smoke.xml | 216 ++++++++--------- ...oromechanics_FaultModel_well_seq_smoke.xml | 229 +++++++++--------- 2 files changed, 220 insertions(+), 225 deletions(-) diff --git a/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_fim_smoke.xml b/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_fim_smoke.xml index c408db31a9d..0ce10628d75 100644 --- a/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_fim_smoke.xml +++ b/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_fim_smoke.xml @@ -1,136 +1,134 @@ - - + + + gravityVector="{ 0.0, 0.0, -9.81 }"> + + name="reservoirSolver" + targetRegions="{ Region, Fault }" + initialDt="3600" + reservoirAndWellsSolverName="reservoirAndWellsSolver" + solidSolverName="fractureMechSolver" + logLevel="3"> - + couplingType="FullyImplicit" + lineSearchAction="None" + maxTimeStepCuts="10" + newtonTol="1e-2" + newtonMaxIter="20" + maxAllowedResidualNorm="1e+15" /> - + directParallel="0" /> + - + name="fractureMechSolver" + stabilizationName="TPFA_stab" + logLevel="1" + targetRegions="{ Region, Fault }" + discretization="FE1" /> + - - - + name="reservoirAndWellsSolver" + flowSolverName="flowSolver" + wellSolverName="wellSolver" + targetRegions="{ Region, Fault, wellInjector }" + logLevel="3" /> + + + + name="wellSolver" + targetRegions="{ wellInjector }" + writeCSV="1" + useMass="1" + logLevel="2"> - - - - - + name="injectorControls" + type="injector" + referenceElevation="-2250" + targetBHP="10e9" + targetTotalRate="6673.48812509" + useSurfaceConditions="1" + surfacePressure="1.01325e6" + surfaceTemperature="367.15" + control="totalVolRate" + enableCrossflow="0" + injectionStream="{ 1.00, 0.00 }" + injectionTemperature="368.15" + logLevel="2" /> + + name="mesh1" + useGlobalIds="1" + faceBlocks="{ fracture }" + file="verticalFault_ExternalMesh.vtm"> + name="well_injector" + logLevel="1" + wellRegionName="wellInjector" + wellControlsName="injectorControls" + polylineNodeCoords="{ { -600, -600, -2000 }, + { -600, -600, -2500 } }" + polylineSegmentConn="{ { 0, 1 } }" + radius="0.1" + numElementsPerSegment="1"> - + name="injector_perf1" + distanceFromHead="250" /> - + + - - + minTime="-1e11" + maxTime="111600"> + + + + - + name="outputPostEquilibrationStep1" + targetTime="0" + targetExactTimestep="1" + target="/Outputs/vtkOutput" /> + - + name="solverApplication" + endTime="1.0e5" + maxEventDt="1.0e5" + target="/Solvers/reservoirSolver" /> + - + name="outputs" + beginTime="0.0" + endTime="1.0e5" + timeFrequency="1.0e5" + target="/Outputs/vtkOutput" /> + - + name="restarts" + beginTime="0.0" + timeFrequency="1.0e5" + endTime="1.0e5" + target="/Outputs/restartOutput" /> diff --git a/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_seq_smoke.xml b/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_seq_smoke.xml index cf99b1875b4..d0959438756 100644 --- a/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_seq_smoke.xml +++ b/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_seq_smoke.xml @@ -1,146 +1,143 @@ - - + + + gravityVector="{ 0.0, 0.0, -9.81 }"> + + name="reservoirSolver" + targetRegions="{ Region, Fault }" + initialDt="3600" + reservoirAndWellsSolverName="reservoirAndWellsSolver" + solidSolverName="fractureMechSolver" + logLevel="3"> - + couplingType="Sequential" + lineSearchAction="None" + maxTimeStepCuts="10" + newtonTol="1e-2" + newtonMaxIter="20" + maxAllowedResidualNorm="1e+15" /> - + directParallel="0" /> + - + name="fractureMechSolver" + stabilizationName="TPFA_stab" + logLevel="1" + targetRegions="{ Region, Fault }" + discretization="FE1" /> + + name="reservoirAndWellsSolver" + flowSolverName="flowSolver" + wellSolverName="wellSolver" + targetRegions="{ Region, Fault, wellInjector }" + logLevel="3"> - + lineSearchAction="None" + maxTimeStepCuts="10" + newtonTol="1e-2" + newtonMaxIter="20" /> - + solverType="fgmres" + preconditionerType="mgr" /> - - + + + + name="wellSolver" + targetRegions="{ wellInjector }" + writeCSV="1" + useMass="1" + logLevel="2"> - - - - - + name="injectorControls" + type="injector" + referenceElevation="-2250" + targetBHP="10e9" + targetTotalRate="6673.48812509" + useSurfaceConditions="1" + surfacePressure="1.01325e6" + surfaceTemperature="367.15" + control="totalVolRate" + enableCrossflow="0" + injectionStream="{ 1.00, 0.00 }" + injectionTemperature="368.15" + logLevel="2" /> + + name="mesh1" + useGlobalIds="1" + faceBlocks="{ fracture }" + file="verticalFault_ExternalMesh.vtm"> + name="well_injector" + logLevel="1" + wellRegionName="wellInjector" + wellControlsName="injectorControls" + polylineNodeCoords="{ { -600, -600, -2000 }, + { -600, -600, -2500 } }" + polylineSegmentConn="{ { 0, 1 } }" + radius="0.1" + numElementsPerSegment="1"> - + name="injector_perf1" + distanceFromHead="250" /> - + + - - + minTime="-1e11" + maxTime="111600"> + + + + - + name="outputPostEquilibrationStep1" + targetTime="0" + targetExactTimestep="1" + target="/Outputs/vtkOutput" /> + - + name="solverApplication" + endTime="1.0e5" + maxEventDt="1.0e5" + target="/Solvers/reservoirSolver" /> + - + name="outputs" + beginTime="0.0" + endTime="1.0e5" + timeFrequency="1.0e5" + target="/Outputs/vtkOutput" /> + - + name="restarts" + beginTime="0.0" + timeFrequency="1.0e5" + endTime="1.0e5" + target="/Outputs/restartOutput" /> From 161631a21e26aaad0360ecc084a4e5a80ec58f2c Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Mon, 3 Nov 2025 06:57:10 -0800 Subject: [PATCH 34/71] schema --- ...oromechanics_FaultModel_well_fim_smoke.xml | 66 +++++++++--------- ...oromechanics_FaultModel_well_seq_smoke.xml | 68 ++++++++++--------- 2 files changed, 71 insertions(+), 63 deletions(-) diff --git a/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_fim_smoke.xml b/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_fim_smoke.xml index 0ce10628d75..3660699ecaf 100644 --- a/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_fim_smoke.xml +++ b/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_fim_smoke.xml @@ -1,14 +1,16 @@ + + - + - + maxAllowedResidualNorm="1e+15"/> + directParallel="0"/> + targetRegions="{ Region, Fault }" + discretization="FE1"/> + logLevel="3"/> - + targetRegions="{ Region, Fault }" + temperature="368.15"/> + logLevel="2"> + + + @@ -88,47 +95,44 @@ numElementsPerSegment="1"> + distanceFromHead="250"/> - + + - - - + target="/Outputs/vtkOutput"/> + target="/Solvers/reservoirSolver"/> + target="/Outputs/vtkOutput"/> + target="/Outputs/restartOutput"/> diff --git a/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_seq_smoke.xml b/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_seq_smoke.xml index d0959438756..5557c612313 100644 --- a/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_seq_smoke.xml +++ b/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_seq_smoke.xml @@ -1,14 +1,16 @@ + + - + - + maxAllowedResidualNorm="1e+15"/> + directParallel="0"/> + targetRegions="{ Region, Fault }" + discretization="FE1"/> + newtonMaxIter="20"/> + preconditionerType="mgr"/> - + targetRegions="{ Region, Fault }" + temperature="368.15"/> + logLevel="2"> + + + @@ -97,47 +104,44 @@ numElementsPerSegment="1"> + distanceFromHead="250"/> - + + - - - + target="/Outputs/vtkOutput"/> + target="/Solvers/reservoirSolver"/> + target="/Outputs/vtkOutput"/> + target="/Outputs/restartOutput"/> From 076c1b446d00a9e591c76aa2f7974359e8f2d469 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Mon, 3 Nov 2025 07:29:22 -0800 Subject: [PATCH 35/71] schema --- .../tableFunctionsFileTests/testTableFunctionsOutput.cpp | 1 + .../integrationTests/wellsTests/testOpenClosePerf.cpp | 1 + .../wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/coreComponents/integrationTests/tableFunctionsFileTests/testTableFunctionsOutput.cpp b/src/coreComponents/integrationTests/tableFunctionsFileTests/testTableFunctionsOutput.cpp index 0aaea58d21c..4bbe92d81db 100644 --- a/src/coreComponents/integrationTests/tableFunctionsFileTests/testTableFunctionsOutput.cpp +++ b/src/coreComponents/integrationTests/tableFunctionsFileTests/testTableFunctionsOutput.cpp @@ -95,6 +95,7 @@ char const * xmlInput = type="injector" enableCrossflow="0" useSurfaceConditions="1" + control="totalVolRate" surfacePressure="1.45e7" surfaceTemperature="300.15"> From eb25cac78c465f3004f75fa1b8bbe66cd8155842 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Mon, 3 Nov 2025 08:12:51 -0800 Subject: [PATCH 36/71] schema --- .../integrationTests/wellsTests/testOpenClosePerf.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp b/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp index 65fb48f6160..5502909a7c5 100644 --- a/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp @@ -72,7 +72,6 @@ char const * PreXmlInput = From 6275e7e74a2aea11f0200ebef912802602160ae4 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 4 Nov 2025 11:58:48 -0800 Subject: [PATCH 37/71] parallel fix, ensure all rank have well constraint state, fix integrate --- .../mesh/WellElementSubRegion.hpp | 7 ++ .../wells/CompositionalMultiphaseWell.cpp | 69 ++++++++++++------- .../fluidFlow/wells/WellControls.hpp | 3 +- 3 files changed, 51 insertions(+), 28 deletions(-) diff --git a/src/coreComponents/mesh/WellElementSubRegion.hpp b/src/coreComponents/mesh/WellElementSubRegion.hpp index 26089a42838..af6a823dd12 100644 --- a/src/coreComponents/mesh/WellElementSubRegion.hpp +++ b/src/coreComponents/mesh/WellElementSubRegion.hpp @@ -223,6 +223,13 @@ class WellElementSubRegion : public ElementSubRegionBase m_topRank = rank; } + /** + * @brief Get for the MPI rank that owns this well (i.e. the top segment). + */ + int getTopRank() const + { + return m_topRank; + } /** * @brief Check if well is owned by current rank * @return true if the well is owned by current rank, false otherwise diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index e376f0d33aa..b3e11795af2 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -469,6 +469,7 @@ void CompositionalMultiphaseWell::postRestartInitialization() // loop over the wells mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, WellElementSubRegion & subRegion ) + { // setup fluid separator WellControls & wellControls = getWellControls( subRegion ); @@ -1007,6 +1008,27 @@ real64 CompositionalMultiphaseWell::updateSubRegionState( WellElementSubRegion & // update the current BHP updateBHPForConstraint( subRegion ); + // Broad case the updated well state to other ranks + real64 & currentBHP = + wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() ); + array1d< real64 > currentPhaseVolRate = + wellControls.getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ); + real64 & currentTotalVolRate = + wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() ); + real64 & currentMassRate = + wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() ); + integer topRank = subRegion.getTopRank(); + MpiWrapper::broadcast( currentBHP, topRank ); + MpiWrapper::bcast( currentPhaseVolRate.data(), LvArray::integerConversion< int >( currentPhaseVolRate.size() ), topRank ); + MpiWrapper::broadcast( currentTotalVolRate, topRank ); + MpiWrapper::broadcast( currentMassRate, topRank ); + if( !subRegion.isLocallyOwned() ) + { + wellControls.getReference< array1d< real64 > >( + CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) =currentPhaseVolRate; + + + } } else { @@ -1437,36 +1459,30 @@ void CompositionalMultiphaseWell::assembleWellAccumulationTerms( real64 const & } else { -//wellControls.setWellOpen(false); -// get the degrees of freedom and ghosting info - // get the degrees of freedom and ghosting info arrayView1d< globalIndex const > const & wellElemDofNumber = subRegion.getReference< array1d< globalIndex > >( wellDofKey ); arrayView1d< integer const > const wellElemGhostRank = subRegion.ghostRank(); - arrayView1d< integer const > const elemStatus = subRegion.getLocalWellElementStatus(); + arrayView1d< real64 > mixConnRate = subRegion.getField< fields::well::mixtureConnectionRate >(); localIndex rank_offset = dofManager.rankOffset(); forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) { if( wellElemGhostRank[ei] < 0 ) { - if( elemStatus[ei]==WellElementSubRegion::WellElemStatus::CLOSED ) - { - mixConnRate[ei] = 0.0; - globalIndex const dofIndex = wellElemDofNumber[ei]; - localIndex const localRow = dofIndex - rank_offset; + mixConnRate[ei] = 0.0; + globalIndex const dofIndex = wellElemDofNumber[ei]; + localIndex const localRow = dofIndex - rank_offset; - real64 const unity = 1.0; - for( integer i=0; i < m_numDofPerWellElement; i++ ) - { - globalIndex const rindex = localRow+i; - globalIndex const cindex =dofIndex + i; - localMatrix.template addToRow< serialAtomic >( rindex, - &cindex, - &unity, - 1 ); - localRhs[rindex] = 0.0; - } + real64 const unity = 1.0; + for( integer i=0; i < m_numDofPerWellElement; i++ ) + { + globalIndex const rindex = localRow+i; + globalIndex const cindex =dofIndex + i; + localMatrix.template addToRow< serialAtomic >( rindex, + &cindex, + &unity, + 1 ); + localRhs[rindex] = 0.0; } } } ); @@ -2216,15 +2232,10 @@ CompositionalMultiphaseWell::applyWellSystemSolution( DofManager const & dofMana fields::well::mixtureConnectionRate::key(), scalingFactor, connRateMask ); - arrayView1d< real64 const > const & temp =subRegion.getField< fields::well::temperature >(); + if( isThermal() ) { DofManager::CompMask temperatureMask( m_numDofPerWellElement, numFluidComponents()+2, numFluidComponents()+3 ); - - for( integer i=0; i(constraint->getControl()) ); // tjb old wellControls.setCurrentConstraint( constraint ); + constraint->setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); + constraint->setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( + CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); + constraint->setTotalVolumeRate ( wellControls.getReference< real64 >( + CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); + constraint->setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), " Well " << subRegion.getName() << " New Limiting Constraint " << constraint->getName() << " " << constraint->getConstraintValue( time_n ) ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp index 22218827d9a..625891c00ff 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp @@ -450,6 +450,7 @@ class WellControls : public dataRepository::Group WellControls::Status getWellStatus () const { return m_wellStatus; } ///@} + /** * @brief Struct to serve as a container for variable strings and keys. * @struct viewKeyStruct @@ -606,11 +607,9 @@ class WellControls : public dataRepository::Group std::vector< WellConstraintBase * > m_productionRateConstraintList; std::vector< WellConstraintBase * > m_injectionRateConstraintList; - /// Well status WellControls::Status m_wellStatus; - /// Region average pressure used in volume rate constraint calculations real64 m_regionAveragePressure; From ed20bafa5ea327fbd78c3ae732adc72c69c6e11a Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 4 Nov 2025 13:28:23 -0800 Subject: [PATCH 38/71] remove std::cout --- .../wells/CompositionalMultiphaseWell.cpp | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index b3e11795af2..23f9800aed1 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -2367,22 +2367,8 @@ void CompositionalMultiphaseWell::chopNegativeDensities( WellElementSubRegion & arrayView2d< real64, compflow::USD_COMP > const & wellElemCompDens = subRegion.getField< fields::well::globalCompDensity >(); - //arrayView2d< real64, compflow::USD_COMP > const & wellElemCompDens_n = - // subRegion.getField< fields::well::globalCompDensity_n >(); - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) { - /* - for( integer ic = 0; ic < numComp; ++ic ) - { - if( iwelem == 65 ) - { - std::cout << "tjb dens " << iwelem << " " << ic << " " << wellElemCompDens[iwelem][ic] << " " << - wellElemCompDens_n[iwelem][ic] << - std::endl; - } - } - */ if( wellElemGhostRank[iwelem] < 0 ) { for( integer ic = 0; ic < numComp; ++ic ) @@ -2981,9 +2967,6 @@ bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, if( limitingConstraint->getName() != constraint->getName()) { - //std::cout << "Use estimator " << useEstimator << " Evaluating constraint " << constraint.getName() << " against constraint " - // << - // limitingConstraint->getName() << std::endl; if( constraint->checkViolation( *limitingConstraint, time_n ) ) { limitingConstraint = constraint; From 79619cd4c6945fc3ea4c029cb555c4894378da0e Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 4 Nov 2025 14:50:49 -0800 Subject: [PATCH 39/71] doxy fix --- .../mesh/WellElementSubRegion.hpp | 1 + .../wells/CompositionalMultiphaseWell.cpp | 36 ------------------- 2 files changed, 1 insertion(+), 36 deletions(-) diff --git a/src/coreComponents/mesh/WellElementSubRegion.hpp b/src/coreComponents/mesh/WellElementSubRegion.hpp index af6a823dd12..4be7cf48e3b 100644 --- a/src/coreComponents/mesh/WellElementSubRegion.hpp +++ b/src/coreComponents/mesh/WellElementSubRegion.hpp @@ -225,6 +225,7 @@ class WellElementSubRegion : public ElementSubRegionBase /** * @brief Get for the MPI rank that owns this well (i.e. the top segment). + * @return the rank that owns the top well element */ int getTopRank() const { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index fa4724c0913..cf107da5144 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -389,43 +389,7 @@ void CompositionalMultiphaseWell::validateConstitutiveModels( DomainPartition co } ); } -void CompositionalMultiphaseWell::validateInjectionStreams( WellElementSubRegion const & subRegion ) const -{ - WellControls const & wellControls = getWellControls( subRegion ); - - // check well injection stream for injectors - if( wellControls.isInjector()) - { - arrayView1d< real64 const > const & injectionStream = wellControls.getInjectionStream(); - - integer const streamSize = injectionStream.size(); - GEOS_THROW_IF( ( streamSize == 0 ), - "WellControls " << wellControls.getName() << - " : Injection stream not specified for well " << subRegion.getName(), - InputError ); - GEOS_THROW_IF( ( streamSize != m_numComponents ), - "WellControls " << wellControls.getName() << - " : Injection stream for well " << subRegion.getName() << " should have " << - m_numComponents << " components.", - InputError ); - real64 compFracSum = 0; - for( integer ic = 0; ic < m_numComponents; ++ic ) - { - real64 const compFrac = injectionStream[ic]; - GEOS_THROW_IF( ( compFrac < 0.0 ) || ( compFrac > 1.0 ), - "WellControls " << wellControls.getDataContext() << - ": Invalid injection stream for well " << subRegion.getName(), - InputError, wellControls.getDataContext() ); - compFracSum += compFrac; - } - GEOS_THROW_IF( ( compFracSum < 1.0 - std::numeric_limits< real64 >::epsilon() ) || - ( compFracSum > 1.0 + std::numeric_limits< real64 >::epsilon() ), - "WellControls " << wellControls.getDataContext() << - ": Invalid injection stream for well " << subRegion.getName(), - InputError, wellControls.getDataContext() ); - } -} void CompositionalMultiphaseWell::validateWellConstraints( real64 const & time_n, real64 const & GEOS_UNUSED_PARAM( dt ), From dff8951cfa9533746a93fded9d3bf94ec9f675ae Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Wed, 5 Nov 2025 09:24:51 -0800 Subject: [PATCH 40/71] see if this helps the problematic clang build --- .github/workflows/ci_tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 88decc83bda..8321c869baf 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -212,6 +212,7 @@ jobs: GEOS_ENABLE_BOUNDS_CHECK: ON BUILD_SHARED_LIBS: ON HOST_CONFIG: /spack-generated.cmake + USE_SCCACHE: false #- name: Sherlock CPU (centos 7.9.2009, gcc 10.1.0, open-mpi 4.1.2, openblas 0.3.10) # CMAKE_BUILD_TYPE: Release From b1eb90caea1ea688d559b23314b8ed3b0cf94445 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Wed, 5 Nov 2025 10:39:29 -0800 Subject: [PATCH 41/71] disable clang --- .github/workflows/ci_tests.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 8321c869baf..429f5836282 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -204,15 +204,15 @@ jobs: GEOS_ENABLE_BOUNDS_CHECK: OFF HOST_CONFIG: /spack-generated.cmake - - name: Ubuntu (22.04, clang 15.0.7, open-mpi 4.1.2) - CMAKE_BUILD_TYPE: Release - DOCKER_REPOSITORY: geosx/ubuntu22.04-clang15 - ENABLE_HYPRE: ON - ENABLE_TRILINOS: OFF - GEOS_ENABLE_BOUNDS_CHECK: ON - BUILD_SHARED_LIBS: ON - HOST_CONFIG: /spack-generated.cmake - USE_SCCACHE: false + #- name: Ubuntu (22.04, clang 15.0.7, open-mpi 4.1.2) + # CMAKE_BUILD_TYPE: Release + # DOCKER_REPOSITORY: geosx/ubuntu22.04-clang15 + # ENABLE_HYPRE: ON + ## ENABLE_TRILINOS: OFF + # GEOS_ENABLE_BOUNDS_CHECK: ON + # BUILD_SHARED_LIBS: ON + # HOST_CONFIG: /spack-generated.cmake + # USE_SCCACHE: false #- name: Sherlock CPU (centos 7.9.2009, gcc 10.1.0, open-mpi 4.1.2, openblas 0.3.10) # CMAKE_BUILD_TYPE: Release From ea002fc237754df0d3f561178e8fc0ec0d599624 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Fri, 7 Nov 2025 12:19:05 -0800 Subject: [PATCH 42/71] fix schema input, zero out constraint qtys if well shut, fix error msh --- .../soreideWhitson/1D_100cells/1D_smoke.xml | 6 --- .../wells/CompositionalMultiphaseWell.cpp | 44 +++++++++++++++++-- .../fluidFlow/wells/WellConstraintsBase.cpp | 2 +- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml index d7df3eba0ce..3e4fe211b1b 100644 --- a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml +++ b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml @@ -48,9 +48,6 @@ enableCrossflow="0" logLevel="0" control="totalVolRate"> - - ( subRegion, fluidName ); integer const numPhases = fluid.numFluidPhases(); integer const numComponents = fluid.numFluidComponents(); - WellControls const & wellControls = getWellControls( subRegion ); + WellControls & wellControls = getWellControls( subRegion ); if( wellControls.getWellStatus() == WellControls::Status::OPEN && !m_keepVariablesConstantDuringInitStep ) { if( isThermal() ) @@ -1459,6 +1459,38 @@ void CompositionalMultiphaseWell::assembleWellAccumulationTerms( real64 const & localMatrix, localRhs ); } + // get the degrees of freedom and ghosting info + arrayView1d< globalIndex const > const & wellElemDofNumber = + subRegion.getReference< array1d< globalIndex > >( wellDofKey ); + arrayView1d< integer const > const wellElemGhostRank = subRegion.ghostRank(); + arrayView1d< integer const > const elemStatus = subRegion.getLocalWellElementStatus(); + arrayView1d< real64 > const mixConnRate = subRegion.getField< fields::well::mixtureConnectionRate >(); + localIndex rank_offset = dofManager.rankOffset(); + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + if( wellElemGhostRank[ei] < 0 ) + { + if( elemStatus[ei]==WellElementSubRegion::WellElemStatus::CLOSED ) + { + mixConnRate[ei] = 0.0; + globalIndex const dofIndex = wellElemDofNumber[ei]; + localIndex const localRow = dofIndex - rank_offset; + + real64 const unity = 1.0; + for( integer i=0; i < m_numDofPerWellElement; i++ ) + { + globalIndex const rindex = localRow+i; + globalIndex const cindex =dofIndex + i; + localMatrix.template addToRow< serialAtomic >( rindex, + &cindex, + &unity, + 1 ); + localRhs[rindex] = 0.0; + } + } + } + } ); + } else { @@ -1489,10 +1521,14 @@ void CompositionalMultiphaseWell::assembleWellAccumulationTerms( real64 const & } } } ); + // zero out current state constraint quantities + wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )=0.0; + wellControls.getReference< array1d< real64 > >( + CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ).zero(); + wellControls.getReference< real64 >( + CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )=0.0; + wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )=0.0; } - - - } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp index 071c86482fb..cdc89300129 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp @@ -93,7 +93,7 @@ void WellConstraintBase::postInputInitialization() { GEOS_THROW_IF( ((m_constraintValue > 0.0 && !m_constraintScheduleTableName.empty())|| (!(m_constraintValue > 0.0) && m_constraintScheduleTableName.empty())), - this->getName() << " " << this->getDataContext() << ": You have provided redundant information for well constraint value ." << + this->getDataContext() << ": You have provided redundant information for well constraint value ." << " A constraint value and table of constraint values cannot be specified together", InputError ); From 0aeb0717a2b1913f534bf43d57c465f4c924eaf4 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Mon, 10 Nov 2025 10:48:43 -0800 Subject: [PATCH 43/71] remove unused schema --- .../wells/CompositionalMultiphaseWell.cpp | 79 +++++++------------ .../fluidFlow/wells/SinglePhaseWell.cpp | 56 +++++-------- .../fluidFlow/wells/WellSolverBase.cpp | 64 ++++++--------- .../fluidFlow/wells/WellSolverBase.hpp | 4 - 4 files changed, 76 insertions(+), 127 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 61574270b4a..60ca66c19e3 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -989,69 +989,50 @@ real64 CompositionalMultiphaseWell::updateSubRegionState( WellElementSubRegion & WellControls & wellControls = getWellControls( subRegion ); if( wellControls.getWellState()) { - if( m_useNewCode ) - { - // update properties - updateGlobalComponentFraction( subRegion ); - - // update densities, phase fractions, phase volume fractions - updateFluidModel( subRegion ); // Calculate fluid properties + // update properties + updateGlobalComponentFraction( subRegion ); - updateSeparator( subRegion ); // Calculate fluid properties at control conditions + // update densities, phase fractions, phase volume fractions - updateVolRatesForConstraint( subRegion ); // remove tjb ?? + updateFluidModel( subRegion ); // Calculate fluid properties - maxPhaseVolChange = updatePhaseVolumeFraction( subRegion ); - updateTotalMassDensity( subRegion ); + updateSeparator( subRegion ); // Calculate fluid properties at control conditions - // Calculate the reference element rates - calculateReferenceElementRates( subRegion ); + updateVolRatesForConstraint( subRegion ); // remove tjb ?? - // update the current BHP - updateBHPForConstraint( subRegion ); + maxPhaseVolChange = updatePhaseVolumeFraction( subRegion ); + updateTotalMassDensity( subRegion ); - // Broad case the updated well state to other ranks - real64 & currentBHP = - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() ); - array1d< real64 > currentPhaseVolRate = - wellControls.getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ); - real64 & currentTotalVolRate = - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() ); - real64 & currentMassRate = - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() ); - integer topRank = subRegion.getTopRank(); - MpiWrapper::broadcast( currentBHP, topRank ); - MpiWrapper::bcast( currentPhaseVolRate.data(), LvArray::integerConversion< int >( currentPhaseVolRate.size() ), topRank ); - MpiWrapper::broadcast( currentTotalVolRate, topRank ); - MpiWrapper::broadcast( currentMassRate, topRank ); - if( !subRegion.isLocallyOwned() ) - { - wellControls.getReference< array1d< real64 > >( - CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) =currentPhaseVolRate; + // Calculate the reference element rates + calculateReferenceElementRates( subRegion ); + // update the current BHP + updateBHPForConstraint( subRegion ); - } - } - else + // Broad case the updated well state to other ranks + real64 & currentBHP = + wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() ); + array1d< real64 > currentPhaseVolRate = + wellControls.getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ); + real64 & currentTotalVolRate = + wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() ); + real64 & currentMassRate = + wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() ); + integer topRank = subRegion.getTopRank(); + MpiWrapper::broadcast( currentBHP, topRank ); + MpiWrapper::bcast( currentPhaseVolRate.data(), LvArray::integerConversion< int >( currentPhaseVolRate.size() ), topRank ); + MpiWrapper::broadcast( currentTotalVolRate, topRank ); + MpiWrapper::broadcast( currentMassRate, topRank ); + if( !subRegion.isLocallyOwned() ) { - // update properties - updateGlobalComponentFraction( subRegion ); + wellControls.getReference< array1d< real64 > >( + CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) =currentPhaseVolRate; - // update volumetric rates for the well constraints - // note: this must be called before updateFluidModel - updateVolRatesForConstraint( subRegion ); - - // update densities, phase fractions, phase volume fractions - - updateFluidModel( subRegion ); // Calculate fluid properties; - maxPhaseVolChange = updatePhaseVolumeFraction( subRegion ); - updateTotalMassDensity( subRegion ); - // update the current BHP pressure - updateBHPForConstraint( subRegion ); } + } return maxPhaseVolChange; } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index 9463eb335bc..7338c4566c3 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -452,33 +452,20 @@ real64 SinglePhaseWell::updateSubRegionState( WellElementSubRegion & subRegion ) WellControls & wellControls = getWellControls( subRegion ); if( wellControls.getWellState()) { - if( m_useNewCode ) - { - // update volumetric rates for the well constraints - // Warning! This must be called before updating the fluid model - //calculateReferenceElementRates( subRegion ); - - // update density in the well elements - updateFluidModel( subRegion ); - updateSeparator( subRegion ); // Calculate fluid properties at control conditions - - // Calculate the reference element rates - calculateReferenceElementRates( subRegion ); - // update the current BHP - updateBHPForConstraint( subRegion ); - } - else - { - // update volumetric rates for the well constraints - // Warning! This must be called before updating the fluid model - calculateReferenceElementRates( subRegion ); - // update density in the well elements - updateFluidModel( subRegion ); + // update volumetric rates for the well constraints + // Warning! This must be called before updating the fluid model + //calculateReferenceElementRates( subRegion ); + + // update density in the well elements + updateFluidModel( subRegion ); + updateSeparator( subRegion ); // Calculate fluid properties at control conditions + + // Calculate the reference element rates + calculateReferenceElementRates( subRegion ); + // update the current BHP + updateBHPForConstraint( subRegion ); - // update the current BHP - updateBHPForConstraint( subRegion ); - } } return 0.0; // change in phasevolume fraction doesnt apply @@ -771,16 +758,15 @@ void SinglePhaseWell::assembleSystem( real64 const time, { string const wellDofKey = dofManager.getKey( wellElementDofName()); - if( m_useNewCode ) - { - // selects constraints one of 2 ways - // wellEstimator flag set to 0 => orginal logic rates are computed during update state and constraints are selected every newton - // iteration - // wellEstimator flag > 0 => well esitmator solved for each constraint and then selects the constraint - // => estimator solve only performed first "wellEstimator" iterations - NonlinearSolverParameters const & nonlinearParams = getNonlinearSolverParameters(); - selectWellConstraint( time, dt, nonlinearParams.m_numNewtonIterations, domain ); - } + + // selects constraints one of 2 ways + // wellEstimator flag set to 0 => orginal logic rates are computed during update state and constraints are selected every newton + // iteration + // wellEstimator flag > 0 => well esitmator solved for each constraint and then selects the constraint + // => estimator solve only performed first "wellEstimator" iterations + NonlinearSolverParameters const & nonlinearParams = getNonlinearSolverParameters(); + selectWellConstraint( time, dt, nonlinearParams.m_numNewtonIterations, domain ); + // assemble the accumulation term in the mass balance equations assembleAccumulationTerms( time, dt, domain, dofManager, localMatrix, localRhs ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp index 79470d0865a..6b02201385d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp @@ -43,9 +43,8 @@ WellSolverBase::WellSolverBase( string const & name, m_numDofPerResElement( 0 ), m_isThermal( 0 ), m_ratesOutputDir( joinPath( OutputBase::getOutputDirectory(), name + "_rates" ) ), - m_keepVariablesConstantDuringInitStep( false ), + m_keepVariablesConstantDuringInitStep( false ) - m_useNewCode( true ) { registerWrapper( viewKeyStruct::isThermalString(), &m_isThermal ). setApplyDefaultValue( 0 ). @@ -65,11 +64,6 @@ WellSolverBase::WellSolverBase( string const & name, setInputFlag( dataRepository::InputFlags::OPTIONAL ). setDescription( "Choose time step to honor rates/bhp tables time intervals" ); - this->registerWrapper( viewKeyStruct::useNewCodeString(), &m_useNewCode ). - setApplyDefaultValue( 1 ). - setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Use new code" ); - addLogLevel< logInfo::WellControl >(); } @@ -301,12 +295,6 @@ void WellSolverBase::implicitStepSetup( real64 const & time_n, // Open close perfs setPerforationStatus( time_n, domain ); - // Initialize the primary and secondary variables for the first time step - if( !m_useNewCode ) - { - initializeWells( domain, time_n ); - } - } void WellSolverBase::selectWellConstraint( real64 const & time_n, @@ -393,16 +381,15 @@ void WellSolverBase::assembleSystem( real64 const time, arrayView1d< real64 > const & localRhs ) { - if( m_useNewCode ) - { - // selects constraints one of 2 ways - // wellEstimator flag set to 0 => orginal logic rates are computed during update state and constraints are selected every newton - // iteration - // wellEstimator flag > 0 => well esitmator solved for each constraint and then selects the constraint - // => estimator solve only performed first "wellEstimator" iterations - NonlinearSolverParameters const & nonlinearParams = getNonlinearSolverParameters(); - selectWellConstraint( time, dt, nonlinearParams.m_numNewtonIterations, domain ); - } + + // selects constraints one of 2 ways + // wellEstimator flag set to 0 => orginal logic rates are computed during update state and constraints are selected every newton + // iteration + // wellEstimator flag > 0 => well esitmator solved for each constraint and then selects the constraint + // => estimator solve only performed first "wellEstimator" iterations + NonlinearSolverParameters const & nonlinearParams = getNonlinearSolverParameters(); + selectWellConstraint( time, dt, nonlinearParams.m_numNewtonIterations, domain ); + // assemble the accumulation term in the mass balance equations @@ -410,25 +397,24 @@ void WellSolverBase::assembleSystem( real64 const time, // then assemble the pressure relations between well elements assemblePressureRelations( time, dt, domain, dofManager, localMatrix, localRhs ); - //if( false && m_useNewCode ) + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) { - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) + ElementRegionManager & elementRegionManager = mesh.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) { - ElementRegionManager & elementRegionManager = mesh.getElemManager(); - elementRegionManager.forElementRegions< WellElementRegion >( regionNames, - [&]( localIndex const, - WellElementRegion & region ) - { - WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) - .getGroup< WellElementSubRegion >( region.getSubRegionName() ); - WellControls & wellControls = getWellControls( subRegion ); - if( !wellControls.getConstraintSwitch() ) - assembleWellConstraintTerms( time, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); - } ); + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = getWellControls( subRegion ); + if( !wellControls.getConstraintSwitch() ) + assembleWellConstraintTerms( time, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); } ); - } + } ); + // then compute the perforation rates (later assembled by the coupled solver) computePerforationRates( time, dt, domain ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp index ae1ff3194db..7f0e0c3bf29 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp @@ -396,7 +396,6 @@ class WellSolverBase : public PhysicsSolverBase static constexpr char const * isThermalString() { return "isThermal"; } static constexpr char const * writeCSVFlagString() { return "writeCSV"; } static constexpr char const * timeStepFromTablesFlagString() { return "timeStepFromTables"; } - static constexpr char const * useNewCodeString() { return "useNewCode"; } static constexpr char const * fluidNamesString() { return "fluidNames"; } }; @@ -471,9 +470,6 @@ class WellSolverBase : public PhysicsSolverBase /// flag to use the estimator integer m_estimateSolution; - - integer m_useNewCode; - }; } From f9f7f32994e7e9c7fed5d8db2833914b482f1058 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 2 Dec 2025 10:14:25 -0800 Subject: [PATCH 44/71] merge fixes --- .../wells/CompositionalMultiphaseWell.cpp | 40 +++++++++---- .../wells/CompositionalMultiphaseWell.hpp | 16 +++-- .../fluidFlow/wells/SinglePhaseWell.cpp | 60 ++++++++----------- .../fluidFlow/wells/SinglePhaseWell.hpp | 27 +++------ .../fluidFlow/wells/WellSolverBase.hpp | 18 +++--- 5 files changed, 81 insertions(+), 80 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 25f1dff464e..b8aa59c8241 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -552,7 +552,7 @@ void CompositionalMultiphaseWell::updateBHPForConstraint( WellElementSubRegion & } -void CompositionalMultiphaseWell::updateVolRatesForConstraint( ElementRegionManager const & elemManager, WellElementSubRegion const & subRegion ) +void CompositionalMultiphaseWell::updateVolRatesForConstraint( WellElementSubRegion const & subRegion ) { GEOS_MARK_FUNCTION; @@ -785,7 +785,7 @@ void CompositionalMultiphaseWell::updateFluidModel( WellElementSubRegion & subRe } -void CompositionalMultiphaseWell::updateSeparator( WellElementSubRegion & subRegion ) +void CompositionalMultiphaseWell::updateSeparator( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) { GEOS_MARK_FUNCTION; @@ -825,6 +825,22 @@ void CompositionalMultiphaseWell::updateSeparator( WellElementSubRegion & subReg } else { + if( !wellControls.referenceReservoirRegion().empty() ) + { + ElementRegionBase const & region = elemManager.getRegion( wellControls.referenceReservoirRegion() ); + GEOS_ERROR_IF ( !region.hasWrapper( CompositionalMultiphaseStatistics::regionStatisticsName()), + GEOS_FMT( "{}: WellControl {} referenceReservoirRegion field requires CompositionalMultiphaseStatistics to be configured for region {} ", + getDataContext(), wellControls.getName(), wellControls.referenceReservoirRegion() ) ); + + CompositionalMultiphaseStatistics::RegionStatistics const & stats = region.getReference< CompositionalMultiphaseStatistics::RegionStatistics >( + CompositionalMultiphaseStatistics::regionStatisticsName() ); + GEOS_ERROR_IF( stats.averagePressure <= 0.0, + GEOS_FMT( + "{}: No region average quantities computed. WellControl {} referenceReservoirRegion field requires CompositionalMultiphaseStatistics to be configured for region {} ", + getDataContext(), wellControls.getName(), wellControls.referenceReservoirRegion() )); + wellControls.setRegionAveragePressure( stats.averagePressure ); + wellControls.setRegionAverageTemperature( stats.averageTemperature ); + } // If flashPressure is not set by region the value is defaulted to -1 and indicates to use top segment conditions flashPressure = wellControls.getRegionAveragePressure(); if( flashPressure < 0.0 ) @@ -929,12 +945,11 @@ void CompositionalMultiphaseWell::updateTotalMassDensity( WellElementSubRegion & } -real64 CompositionalMultiphaseWell::updateWellState( WellElementSubRegion & subRegion ) +real64 CompositionalMultiphaseWell::updateWellState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) { GEOS_MARK_FUNCTION; - real64 maxPhaseVolFrac = updateSubRegionState( subRegion ); - + real64 maxPhaseVolFrac = updateSubRegionState( elemManager, subRegion ); return maxPhaseVolFrac; } @@ -956,7 +971,7 @@ void CompositionalMultiphaseWell::updateState( DomainPartition & domain ) if( wellControls.getWellState()) { - real64 const maxRegionPhaseVolFrac = updateWellState( subRegion ); + real64 const maxRegionPhaseVolFrac = updateWellState( elemManager, subRegion ); maxPhaseVolFrac = LvArray::math::max( maxRegionPhaseVolFrac, maxPhaseVolFrac ); } @@ -984,7 +999,7 @@ real64 CompositionalMultiphaseWell::updateSubRegionState( ElementRegionManager c updateFluidModel( subRegion ); // Calculate fluid properties - updateSeparator( subRegion ); // Calculate fluid properties at control conditions + updateSeparator( elemManager, subRegion ); // Calculate fluid properties at control conditions updateVolRatesForConstraint( subRegion ); // remove tjb ?? @@ -1034,12 +1049,12 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh m_nextDt = -1; // TODO: change the way we access the flowSolver here CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); - + ElementRegionManager const & elemManager = mesh.getElemManager(); compositionalMultiphaseWellKernels::PresTempCompFracInitializationKernel::CompFlowAccessors - resCompFlowAccessors( mesh.getElemManager(), flowSolver.getName() ); + resCompFlowAccessors( elemManager, flowSolver.getName() ); compositionalMultiphaseWellKernels::PresTempCompFracInitializationKernel::MultiFluidAccessors - resMultiFluidAccessors( mesh.getElemManager(), flowSolver.getName() ); + resMultiFluidAccessors( elemManager, flowSolver.getName() ); WellControls & wellControls = getWellControls( subRegion ); PerforationData const & perforationData = *subRegion.getPerforationData(); @@ -1153,7 +1168,8 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh wellElemCompDens ); // 5) Recompute the pressure-dependent properties - updateSubRegionState( subRegion ); + + updateSubRegionState( elemManager, subRegion ); // 6) Estimate the well rates // TODO: initialize rates using perforation rates @@ -1189,7 +1205,7 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh // setup if restart if( wellControls.getCurrentConstraint() == nullptr ) { - updateSubRegionState( subRegion ); + updateSubRegionState( elemManager, subRegion ); if( wellControls.isProducer() ) { wellControls.forSubGroups< MinimumBHPConstraint, ProductionConstraint< VolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp index b766106155b..6ad93ec3f44 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp @@ -169,10 +169,9 @@ class CompositionalMultiphaseWell : public WellSolverBase /** * @brief Recompute the volumetric rates that are used in the well constraints - * @param elemManager the well region manager containing the well * @param subRegion the well subregion containing all the primary and dependent fields */ - void updateVolRatesForConstraint( ElementRegionManager const & elemManager, WellElementSubRegion const & subRegion ); + void updateVolRatesForConstraint( WellElementSubRegion const & subRegion ); /** * @brief Recompute the current BHP pressure @@ -190,10 +189,10 @@ class CompositionalMultiphaseWell : public WellSolverBase /** * @brief Update well separator using current values of pressure and composition at the reference element - * @param subRegion the well subregion containing all the primary and dependent fields - * @param targetIndex the targetIndex of the subRegion + * @param elemManager the element region manager + */ - void updateSeparator( WellElementSubRegion & subRegion ); + void updateSeparator( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ); /** * @brief Calculate well rates at reference element @@ -237,7 +236,12 @@ class CompositionalMultiphaseWell : public WellSolverBase * @brief Recompute all dependent quantities from primary variables (including constitutive models) * @param subRegion the well subregion containing all the primary and dependent fields */ - virtual real64 updateWellState( WellElementSubRegion & subRegion ) override; + virtual real64 updateWellState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) override; + /** + * @brief Recompute all dependent quantities from primary variables (including constitutive + * models) + * @param domain the domain containing the mesh and fields + */ virtual void updateState( DomainPartition & domain ) override; virtual real64 updateSubRegionState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) override; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index 9b48dcc65f6..93868f9125e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -164,21 +164,10 @@ void SinglePhaseWell::validateWellConstraints( real64 const & time_n, GEOS_FMT( "{}: Region {} is not a target of the reservoir solver and cannot be used for referenceReservoirRegion in WellControl {}.", getDataContext(), regionName, wellControls.getName() ) ); - ElementRegionBase const & region = elemManager.getRegion( wellControls.referenceReservoirRegion() ); - - // Check if regions statistics are being computed - GEOS_ERROR_IF( !region.hasWrapper( SinglePhaseStatistics::catalogName()), - GEOS_FMT( "{}: No region average quantities computed. WellControl {} referenceReservoirRegion field requires SinglePhaseStatistics to be configured for region {} ", - getDataContext(), wellControls.getName(), regionName )); - - SinglePhaseStatistics::RegionStatistics const & stats = region.getReference< SinglePhaseStatistics::RegionStatistics >( SinglePhaseStatistics::regionStatisticsName() ); - wellControls.setRegionAveragePressure( stats.averagePressure ); - wellControls.setRegionAverageTemperature( stats.averageTemperature ); } } - #if 0 // tjb vix this - WellControls::Control currentControl = wellControls.getControl(); - + // tjb WellControls::Control currentControl = wellControls.getControl(); +#if 0 real64 const targetTotalRate = wellControls.getTargetTotalRate( time_n ); real64 const targetPhaseRate = wellControls.getTargetPhaseRate( time_n ); GEOS_THROW_IF( currentControl == WellControls::Control::PHASEVOLRATE, @@ -194,7 +183,7 @@ void SinglePhaseWell::validateWellConstraints( real64 const & time_n, GEOS_THROW_IF( !isZero( targetPhaseRate ), "WellControls " << wellControls.getDataContext() << ": Target phase rate cannot be used for SinglePhaseWell", - InputError ); + InputError, wellControls.getDataContext() ); #endif } @@ -356,7 +345,7 @@ void SinglePhaseWell::updateFluidModel( WellElementSubRegion & subRegion ) const singlePhaseBaseKernels::FluidUpdateKernel::launch( fluidWrapper, pres, temp ); } ); } -void SinglePhaseWell::updateSeparator( WellElementSubRegion & subRegion ) +void SinglePhaseWell::updateSeparator( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) { GEOS_MARK_FUNCTION; @@ -392,18 +381,19 @@ void SinglePhaseWell::updateSeparator( WellElementSubRegion & subRegion ) { if( !wellControls.referenceReservoirRegion().empty() ) { - ElementRegionBase const & region = elemManager.getRegion( wellControls.referenceReservoirRegion() ); - GEOS_ERROR_IF ( !region.hasWrapper( SinglePhaseStatistics::regionStatisticsName()), + ElementRegionBase const & region = elemManager.getRegion( wellControls.referenceReservoirRegion()); + GEOS_ERROR_IF ( !region.hasWrapper( SinglePhaseStatistics::regionStatisticsName() ), GEOS_FMT( "{}: WellControl {} referenceReservoirRegion field requires SinglePhaseStatistics to be configured for region {} ", getDataContext(), wellControls.getName(), wellControls.referenceReservoirRegion() ) ); - SinglePhaseStatistics::RegionStatistics const & stats = region.getReference< SinglePhaseStatistics::RegionStatistics >( SinglePhaseStatistics::regionStatisticsName() ); - GEOS_ERROR_IF( stats.averagePressure <= 0.0, - GEOS_FMT( - "{}: No region average quantities computed. WellControl {} referenceReservoirRegion field requires SinglePhaseStatistics to be configured for region {} ", - getDataContext(), wellControls.getName(), wellControls.referenceReservoirRegion() )); + SinglePhaseStatistics::RegionStatistics const & stats = region.getReference< SinglePhaseStatistics::RegionStatistics >( + SinglePhaseStatistics::regionStatisticsName() ); wellControls.setRegionAveragePressure( stats.averagePressure ); wellControls.setRegionAverageTemperature( stats.averageTemperature ); + GEOS_ERROR_IF( stats.averagePressure <= 0.0, + GEOS_FMT( "{}: No region average quantities computed. WellControl {} referenceReservoirRegion field requires CompositionalMultiphaseStatistics to be configured for region {} ", + getDataContext(), wellControls.getName(), wellControls.referenceReservoirRegion() )); + } // use region conditions flashPressure = wellControls.getRegionAveragePressure(); @@ -461,7 +451,7 @@ void SinglePhaseWell::updateSeparator( WellElementSubRegion & subRegion ) } ); } -real64 SinglePhaseWell::updateSubRegionState( WellElementSubRegion & subRegion ) +real64 SinglePhaseWell::updateSubRegionState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) { WellControls & wellControls = getWellControls( subRegion ); if( wellControls.getWellState()) @@ -473,7 +463,7 @@ real64 SinglePhaseWell::updateSubRegionState( WellElementSubRegion & subRegion ) // update density in the well elements updateFluidModel( subRegion ); - updateSeparator( subRegion ); // Calculate fluid properties at control conditions + updateSeparator( elemManager, subRegion ); // Calculate fluid properties at control conditions // Calculate the reference element rates calculateReferenceElementRates( subRegion ); @@ -489,7 +479,7 @@ void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh GEOS_UNUSED_VAR( domain ); WellControls & wellControls = getWellControls( subRegion ); PerforationData const & perforationData = *subRegion.getPerforationData(); - + ElementRegionManager const & elemManager = mesh.getElemManager(); // get the info stored on well elements arrayView1d< real64 const > const wellElemGravCoef = subRegion.getField< well::gravityCoefficient >(); @@ -547,8 +537,9 @@ void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh // TODO: change the way we access the flowSolver here SinglePhaseBase const & flowSolver = getParent().getGroup< SinglePhaseBase >( getFlowSolverName() ); - PresTempInitializationKernel::SinglePhaseFlowAccessors resSinglePhaseFlowAccessors( mesh.getElemManager(), flowSolver.getName() ); - PresTempInitializationKernel::SingleFluidAccessors resSingleFluidAccessors( mesh.getElemManager(), flowSolver.getName() ); + + PresTempInitializationKernel::SinglePhaseFlowAccessors resSinglePhaseFlowAccessors( elemManager, flowSolver.getName() ); + PresTempInitializationKernel::SingleFluidAccessors resSingleFluidAccessors( elemManager, flowSolver.getName() ); // 1) Loop over all perforations to compute an average density // 2) Initialize the reference pressure @@ -574,7 +565,7 @@ void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh // 4) Recompute the pressure-dependent properties // Note: I am leaving that here because I would like to use the perforationRates (computed in UpdateState) // to better initialize the rates - updateSubRegionState( subRegion ); + updateSubRegionState( elemManager, subRegion ); string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); SingleFluidBase & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); @@ -607,7 +598,7 @@ void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh // setup for restart if( wellControls.getCurrentConstraint() == nullptr ) { - updateSubRegionState( subRegion ); + updateSubRegionState( elemManager, subRegion ); if( wellControls.isProducer() ) { wellControls.forSubGroups< MinimumBHPConstraint, ProductionConstraint< VolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, @@ -736,11 +727,11 @@ void SinglePhaseWell::shutDownWell( real64 const time_n, } ); } -real64 SinglePhaseWell::updateWellState( WellElementSubRegion & subRegion ) +real64 SinglePhaseWell::updateWellState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) { GEOS_MARK_FUNCTION; - updateSubRegionState( subRegion ); + updateSubRegionState( elemManager, subRegion ); return 0.0; } void SinglePhaseWell::updateState( DomainPartition & domain ) @@ -751,13 +742,14 @@ void SinglePhaseWell::updateState( DomainPartition & domain ) MeshLevel & mesh, string_array const & regionNames ) { - mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, - WellElementSubRegion & subRegion ) + ElementRegionManager & elemManager = mesh.getElemManager(); + elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, + WellElementSubRegion & subRegion ) { WellControls & wellControls = getWellControls( subRegion ); if( wellControls.getWellState()) { - updateWellState( subRegion ); + updateWellState( elemManager, subRegion ); } } ); } ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp index 5b314c65369..fb22dd9feb5 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp @@ -181,9 +181,10 @@ class SinglePhaseWell : public WellSolverBase virtual void updateFluidModel( WellElementSubRegion & subRegion ) const; /** * @brief Update separator model state + * @param elemManager the element region manager * @param subRegion the well subRegion containing the separator */ - void updateSeparator( WellElementSubRegion & subRegion ); + void updateSeparator( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ); /** * @brief Recompute the perforation rates for all the wells @@ -195,21 +196,16 @@ class SinglePhaseWell : public WellSolverBase /** * @brief Recompute all dependent quantities from primary variables (including constitutive * models) - * @param domain the domain containing the mesh and fields - */ - virtual real64 updateWellState( WellElementSubRegion & subRegion ) override; - virtual void updateState( DomainPartition & domain ) override; - /** - * @brief Recompute all dependent quantities from primary variables (including constitutive - * models) - * @param domain the domain containing the mesh and fields + * @param + * @param subRegion the well subRegion containing the well elements and their associated */ - virtual real64 updateWellState( WellElementSubRegion & subRegion ) override; + virtual real64 updateWellState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) override; virtual void updateState( DomainPartition & domain ) override; /** * @brief Recompute all dependent quantities from primary variables (including constitutive models) + * @param elemManager the element region manager * @param subRegion the well subRegion containing the well elements and their associated fields */ virtual real64 updateSubRegionState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) override; @@ -383,19 +379,12 @@ class SinglePhaseWell : public WellSolverBase */ virtual void validateWellConstraints( real64 const & time_n, real64 const & dt, - WellElementSubRegion const & subRegion ,ElementRegionManager const & elemManager - ) override; + WellElementSubRegion const & subRegion + ) override; virtual bool evaluateConstraints( real64 const & time_n, WellElementSubRegion & subRegion ) override; - /** - * @brief Create well separator - */ - void createSeparator(); - - virtual bool evaluateConstraints( real64 const & time_n, - WellElementSubRegion & subRegion ) override; /** * @brief Create well separator diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp index 974c44c9e01..9de04730e26 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp @@ -271,12 +271,18 @@ class WellSolverBase : public PhysicsSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) = 0; + /** + * @brief Recompute all dependent quantities from primary variables (including constitutive + * models) + * @param elemManager the element region manager + * @param subRegion the well subRegion containing the well elements and their associated fields + */ + virtual real64 updateWellState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) = 0; /** * @brief Recompute all dependent quantities from primary variables (including constitutive * models) * @param domain the domain containing the mesh and fields */ - virtual real64 updateWellState( WellElementSubRegion & subRegion ) = 0; virtual void updateState( DomainPartition & domain ) override; /** @@ -289,16 +295,10 @@ class WellSolverBase : public PhysicsSolverBase /** * @brief Recompute all dependent quantities from primary variables (including constitutive * models) - * @param subRegion the well subRegion containing the well elements and their associated + * @param elemManager the element region manager * fields */ - virtual real64 updateSubRegionState( WellElementSubRegion & subRegion ) = 0; - - - virtual void computeWellPerforationRates( real64 const & GEOS_UNUSED_PARAM( time_n ), - real64 const & GEOS_UNUSED_PARAM( dt ), - ElementRegionManager const & GEOS_UNUSED_PARAM( elemManager ), - WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ) ){} + virtual real64 updateSubRegionState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) = 0; virtual void computeWellPerforationRates( real64 const & GEOS_UNUSED_PARAM( time_n ), From 4917a5dfe098491a0e73fa393181e085a291334e Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Fri, 12 Dec 2025 15:37:49 -0800 Subject: [PATCH 45/71] mods to match old constraint behavior, almost --- .../wells/CompositionalMultiphaseWell.cpp | 10 +++++----- .../wells/WellLiquidRateConstraint.cpp | 11 +--------- .../wells/WellMassRateConstraint.cpp | 10 ++-------- .../wells/WellPhaseVolumeRateConstraint.cpp | 9 +-------- .../wells/WellVolumeRateConstraint.cpp | 9 +-------- .../CompositionalMultiphaseWellKernels.cpp | 20 ++++++++++++++++++- 6 files changed, 29 insertions(+), 40 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index b8aa59c8241..7b7d3b5e1ae 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -2510,11 +2510,11 @@ void CompositionalMultiphaseWell::assembleWellConstraintTerms( real64 const & ti // the rank that owns the reference well element is responsible for the calculations below. - if( !subRegion.isLocallyOwned() ) + WellControls & wellControls = getWellControls( subRegion ); + if( !subRegion.isLocallyOwned() || !( wellControls.getWellStatus() == WellControls::Status::OPEN )) { return; } - WellControls & wellControls = getWellControls( subRegion ); if( wellControls.isProducer() ) { @@ -2982,7 +2982,7 @@ bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, limitingConstraint->totalVolumeRate() << " " << limitingConstraint->massRate()); } } - + constraintList.erase( std::find( constraintList.begin(), constraintList.end(), limitingConstraint ) ); // Check current against other constraints for( auto & constraint : constraintList ) @@ -3001,8 +3001,8 @@ bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, constraint->setTotalVolumeRate ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); constraint->setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); - GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), - " Well " << subRegion.getName() << " New Limiting Constraint " << constraint->getName() << " " << constraint->getConstraintValue( time_n ) ); + GEOS_LOG_RANK_IF ( subRegion.isLocallyOwned(), + " Well " << subRegion.getName() << " Control switch " << constraint->getName() << " " << constraint->getConstraintValue( time_n ) ); } } } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.cpp index 54424d9224e..3c84f70f1a7 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.cpp @@ -70,16 +70,7 @@ bool LiquidRateConstraint::checkViolation( WellConstraintBase const & currentCon { real64 const currentValue = currentConstraint.liquidRate(); real64 const constraintValue = this->getConstraintValue( currentTime ); - if( this->m_rateSign < 0.0 ) - { - // production: violated when current < constraint - return currentValue < constraintValue; - } - else - { - // injection: violated when current > constraint - return currentValue > constraintValue; - } + return ( LvArray::math::abs( currentValue ) <= LvArray::math::abs( constraintValue ) ); } } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraint.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraint.cpp index 6851a033f8b..eadffc21b42 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraint.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellMassRateConstraint.cpp @@ -69,13 +69,7 @@ bool MassRateConstraint::checkViolation( WellConstraintBase const & currentConst // Evaluate violation according to the sign set for injectors/producers real64 const currentValue = currentConstraint.massRate(); real64 const constraintValue = this->getConstraintValue( currentTime ); - if( this->m_rateSign < 0.0 ) - { - return currentValue < constraintValue; - } - else - { - return currentValue > constraintValue; - } + return ( LvArray::math::abs( currentValue ) > LvArray::math::abs( constraintValue ) ); + } } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.cpp index 533848b97a3..63f7baa7053 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.cpp @@ -75,14 +75,7 @@ bool PhaseVolumeRateConstraint::checkViolation( WellConstraintBase const & curre { real64 const currentValue = currentConstraint.phaseVolumeRates()[m_phaseIndex]; real64 const constraintValue = getConstraintValue( currentTime ); - if( m_rateSign < 0.0 ) - { - return currentValue < constraintValue; - } - else - { - return currentValue > constraintValue; - } + return ( LvArray::math::abs( currentValue ) > LvArray::math::abs( constraintValue ) ); } } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellVolumeRateConstraint.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellVolumeRateConstraint.cpp index db11dd85ef2..e675af7459e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellVolumeRateConstraint.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellVolumeRateConstraint.cpp @@ -67,14 +67,7 @@ bool VolumeRateConstraint::checkViolation( WellConstraintBase const & currentCon { real64 const currentValue = currentConstraint.totalVolumeRate(); real64 const constraintValue = this->getConstraintValue( currentTime ); - if( this->m_rateSign < 0.0 ) - { - return currentValue < constraintValue; - } - else - { - return currentValue > constraintValue; - } + return ( LvArray::math::abs( currentValue ) > LvArray::math::abs( constraintValue ) ); } } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp index 5c2d4589705..5bbbe14fecd 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp @@ -654,7 +654,7 @@ RateInitializationKernel:: forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) { - connRate[iwelem] = LvArray::math::max( 0.1 * constraintVal * phaseDens[iwelem][0][targetPhaseIndex], -1e3 ); + connRate[iwelem] = constraintVal * phaseDens[iwelem][0][targetPhaseIndex]; } ); } else if( controlType == ConstraintTypeId::TOTALVOLRATE ) @@ -671,6 +671,17 @@ RateInitializationKernel:: connRate[iwelem] = constraintVal; } ); } + else if( controlType == ConstraintTypeId::BHP ) + { + // this assumes phase control presen + integer const targetPhaseIndex = wellControls.getConstraintPhaseIndex(); + + forAll< parallelDevicePolicy<> >( subRegionSize, [&] GEOS_HOST_DEVICE ( localIndex const iwelem ) + { + + connRate[iwelem] = LvArray::math::max( 0.1 * constraintVal * phaseDens[iwelem][0][targetPhaseIndex], -1e3 ); + } ); + } } else { @@ -701,6 +712,13 @@ RateInitializationKernel:: connRate[iwelem] = constraintVal; } ); } + else if( controlType == ConstraintTypeId::BHP ) + { + forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) + { + connRate[iwelem] = LvArray::math::min( 0.1 * constraintVal * totalDens[iwelem][0], 1e3 ); + } ); + } } } From 8fd0b6b8b7b6dc5f7cf9ba107ef9c7a0a110bc80 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Mon, 15 Dec 2025 10:06:13 -0800 Subject: [PATCH 46/71] convert constraint schema --- .../resvol_constraint.xml | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/inputFiles/compositionalMultiphaseWell/resvol_constraint.xml b/inputFiles/compositionalMultiphaseWell/resvol_constraint.xml index 7fe917a2076..cab0d2ed29d 100644 --- a/inputFiles/compositionalMultiphaseWell/resvol_constraint.xml +++ b/inputFiles/compositionalMultiphaseWell/resvol_constraint.xml @@ -32,21 +32,31 @@ name="wellControls1" type="producer" control="BHP" - referenceElevation="2" - targetBHP="4e6" - targetPhaseRate="1e-7" - referenceReservoirRegion="Region1" - targetPhaseName="oil"/> + referenceReservoirRegion="Region1"> + + + + referenceReservoirRegion="Region1"> + + + @@ -61,7 +71,6 @@ ny="{ 1 }" nz="{ 1 }" cellBlockNames="{ cb1 }"> - - + - - + + name="fluidTPFA"/> @@ -192,7 +200,6 @@ - - Date: Wed, 17 Dec 2025 08:46:28 -0800 Subject: [PATCH 47/71] use sep props in constraint calc, fixes integrated test --- .../fluidFlow/wells/SinglePhaseWell.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index 93868f9125e..7ddc8536125 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -301,17 +301,15 @@ void SinglePhaseWell::calculateReferenceElementRates( WellElementSubRegion & sub arrayView1d< real64 const > const & connRate = subRegion.getField< well::connectionRate >(); - // fluid data - - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - SingleFluidBase & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); - arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > const & dens = fluid.density(); - // control data WellControls & wellControls = getWellControls( subRegion ); + // fluid data + constitutive::SingleFluidBase & fluidSeparator = wellControls.getSingleFluidSeparator(); + arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > const & dens = fluidSeparator.density(); + real64 & currentVolRate = wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentVolRateString() ); @@ -891,12 +889,11 @@ void SinglePhaseWell::assembleWellConstraintTerms( real64 const & time_n, // the rank that owns the reference well element is responsible for the calculations below. - if( !subRegion.isLocallyOwned() ) + WellControls & wellControls = getWellControls( subRegion ); + if( !subRegion.isLocallyOwned() || !( wellControls.getWellStatus() == WellControls::Status::OPEN )) { return; } - WellControls & wellControls = getWellControls( subRegion ); - { // tjb wellControls.forSubGroups< BHPConstraint, MassConstraint, VolumeRateConstraint >( [&]( auto & constraint ) wellControls.forSubGroups< BHPConstraint, InjectionConstraint< VolumeRateConstraint >, ProductionConstraint< VolumeRateConstraint > >( [&]( auto & constraint ) @@ -1829,6 +1826,7 @@ bool SinglePhaseWell::evaluateConstraints( real64 const & time_n, } } + constraintList.erase( std::find( constraintList.begin(), constraintList.end(), limitingConstraint ) ); // Check current against other constraints for( auto & constraint : constraintList ) @@ -1836,7 +1834,6 @@ bool SinglePhaseWell::evaluateConstraints( real64 const & time_n, if( limitingConstraint->getName() != constraint->getName()) { - //std::cout << "Use estimator " << useEstimator << " Evaluating constraint " << constraint.getName() << " against constraint " << // limitingConstraint->getName() << std::endl; if( constraint->checkViolation( *limitingConstraint, time_n ) ) { From f03a9cf7ae1e985b4e70dbd791ae7a63c6faa0d1 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Fri, 19 Dec 2025 06:36:47 -0800 Subject: [PATCH 48/71] make 1) rate initialization consistent with develop and 2) force residual check to include all wells (bug) --- .../wells/CompositionalMultiphaseWell.cpp | 2 +- .../CompositionalMultiphaseWellKernels.cpp | 29 +++++++++++-------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 7b7d3b5e1ae..3515711e05c 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -1679,7 +1679,7 @@ CompositionalMultiphaseWell::calculateResidualNorm( real64 const & time_n, WellControls const & wellControls = getWellControls( subRegion ); // step 1: compute the norm in the subRegion - if( wellControls.isWellOpen( ) ) + if( true ) // tjb wellControls.isWellOpen( ) ) { if( isThermal() ) { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp index 5bbbe14fecd..344c66a68c5 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp @@ -644,10 +644,10 @@ RateInitializationKernel:: { if( wellControls.isProducer() ) { - std::vector< WellConstraintBase * > const constraints = wellControls.getProdRateConstraints(); - // Use first rate constraint to set initial connection rates - real64 const constraintVal = constraints[0]->getConstraintValue( time ); - ConstraintTypeId const controlType = constraints[0]->getControl(); + // Use use defined control type to set initial connection rates + WellConstraintBase const * constraint = wellControls.getCurrentConstraint(); + real64 const constraintVal = constraint->getConstraintValue( time ); + ConstraintTypeId const controlType = constraint->getControl(); if( controlType == ConstraintTypeId::PHASEVOLRATE ) { integer const targetPhaseIndex = wellControls.getConstraintPhaseIndex(); @@ -673,22 +673,24 @@ RateInitializationKernel:: } else if( controlType == ConstraintTypeId::BHP ) { - // this assumes phase control presen + // this assumes phase control present integer const targetPhaseIndex = wellControls.getConstraintPhaseIndex(); - + std::vector< WellConstraintBase * > const constraints = wellControls.getProdRateConstraints(); + // Use first rate constraint to set initial connection rates + real64 const rateVal = constraints[0]->getConstraintValue( time ); forAll< parallelDevicePolicy<> >( subRegionSize, [&] GEOS_HOST_DEVICE ( localIndex const iwelem ) { - connRate[iwelem] = LvArray::math::max( 0.1 * constraintVal * phaseDens[iwelem][0][targetPhaseIndex], -1e3 ); + connRate[iwelem] = LvArray::math::max( 0.1 * rateVal * phaseDens[iwelem][0][targetPhaseIndex], -1e3 ); } ); } } else { - std::vector< WellConstraintBase * > const constraints = wellControls.getInjRateConstraints(); - // Use first rate constraint to set initial connection rates - real64 const constraintVal = constraints[0]->getConstraintValue( time ); - ConstraintTypeId const controlType = constraints[0]->getControl(); + // Use use defined control type to set initial connection rates + WellConstraintBase const * constraint = wellControls.getCurrentConstraint(); + real64 const constraintVal = constraint->getConstraintValue( time ); + ConstraintTypeId const controlType = constraint->getControl(); if( controlType == ConstraintTypeId::PHASEVOLRATE ) { integer const targetPhaseIndex = wellControls.getConstraintPhaseIndex(); @@ -714,9 +716,12 @@ RateInitializationKernel:: } else if( controlType == ConstraintTypeId::BHP ) { + std::vector< WellConstraintBase * > const constraints = wellControls.getInjRateConstraints(); + // Use first rate constraint to set initial connection rates + real64 const rateVal = constraints[0]->getConstraintValue( time ); forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) { - connRate[iwelem] = LvArray::math::min( 0.1 * constraintVal * totalDens[iwelem][0], 1e3 ); + connRate[iwelem] = LvArray::math::min( 0.1 * rateVal * totalDens[iwelem][0], 1e3 ); } ); } } From 8cd2d5e18140dca2d644f7daccbba2feaf9f6dbb Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Mon, 12 Jan 2026 04:46:35 -0800 Subject: [PATCH 49/71] reorg prototyping --- .../fluidFlow/wells/WellManager.cpp | 107 ++++++++ .../fluidFlow/wells/WellManager.hpp | 253 ++++++++++++++++++ .../fluidFlow/wells/WellSolverBase.hpp | 6 + 3 files changed, 366 insertions(+) create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp new file mode 100644 index 00000000000..44de4deb621 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp @@ -0,0 +1,107 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file WellManager.cpp + */ + +#include "WellManager.hpp" + +#include "mesh/DomainPartition.hpp" +#include "mesh/PerforationFields.hpp" +#include "mesh/WellElementRegion.hpp" +#include "mesh/WellElementSubRegion.hpp" +#include "physicsSolvers/fluidFlow/wells/LogLevelsInfo.hpp" +#include "physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp" +#include "physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp" +#include "physicsSolvers/fluidFlow/wells/WellSolverBase.hpp" +#include "physicsSolvers/fluidFlow/wells/WellSolverBaseFields.hpp" +#include "fileIO/Outputs/OutputBase.hpp" +#include "functions/FunctionManager.hpp" +namespace geos +{ + +using namespace dataRepository; +using namespace fields; + +WellManager::WellManager( string const & name, + Group * const parent ) + : PhysicsSolverBase( name, parent ) + +{ + this->getWrapper< string >( viewKeyStruct::discretizationString() ). + setInputFlag( InputFlags::FALSE ); +} +Group * WellManager::createChild( string const & childKey, string const & childName ) +{ + static std::set< string > const childTypes = { + keys::compositionalMultiphaseWell, + keys::singlePhaseWell, + PhysicsSolverBase::groupKeyStruct::linearSolverParametersString(), + PhysicsSolverBase::groupKeyStruct::nonlinearSolverParametersString(), + }; + GEOS_ERROR_IF( childTypes.count( childKey ) == 0, + CatalogInterface::unknownTypeError( childKey, getDataContext(), childTypes ), + getDataContext() ); + if( childKey == keys::compositionalMultiphaseWell ) + { + return ®isterGroup< CompositionalMultiphaseWell >( childName ); + } + else if( childKey == keys::singlePhaseWell ) + { + return ®isterGroup< SinglePhaseWell >( childName ); + } + else + { + PhysicsSolverBase::createChild( childKey, childName ); + return nullptr; + } +} + +void WellManager::expandObjectCatalogs() +{ + createChild( keys::compositionalMultiphaseWell, keys::compositionalMultiphaseWell ); + createChild( keys::singlePhaseWell, keys::singlePhaseWell ); +} +WellSolverBase & WellManager::getWell( WellElementSubRegion const & subRegion ) +{ + return this->getGroup< WellSolverBase >( subRegion.getWellControlsName()); +} + +void WellManager::implicitStepSetup( real64 const & time_n, + real64 const & dt, + DomainPartition & domain ) +{ + + forDiscretizationOnMeshTargets ( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + + ElementRegionManager & elemManager = mesh.getElemManager(); + + elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + + WellSolverBase & well = getWell( subRegion ); + well.implicitStepSetup( time_n, dt, domain ); + } ) + ; + } ); +} +REGISTER_CATALOG_ENTRY( PhysicsSolverBase, WellManager, string const &, Group * const ) +} // namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp new file mode 100644 index 00000000000..eb115781edf --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp @@ -0,0 +1,253 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file WellManager.hpp + */ + +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELL_MANAGER_HPP_ +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELL_MANAGER_HPP_ + +#include "physicsSolvers/PhysicsSolverBase.hpp" +#include "physicsSolvers/fluidFlow/wells/WellSolverBase.hpp" + +namespace geos +{ + +class DomainPartition; +class WellControls; +class WellElementSubRegion; + +namespace dataRepository +{ +namespace keys +{ +static constexpr auto compositionalMultiphaseWell = "CompositionalMultiphaseWell"; +static constexpr auto singlePhaseWell = "SinglePhaseWell"; +} +} +/** + * @class WellManager + * + * Base class for well solvers. + * Provides some common features + */ +class WellManager : public PhysicsSolverBase +{ +public: + + /// String used to form the solverName used to register single-physics solvers in CoupledSolver + static string coupledSolverAttributePrefix() { return "well"; } + + /** + * @brief main constructor for Group Objects + * @param name the name of this instantiation of Group in the repository + * @param parent the parent group of this instantiation of Group + */ + WellManager( const string & name, + Group * const parent ); + + /// default destructor + virtual ~WellManager() override = default; + + /// deleted default constructor + WellManager() = delete; + + /// deleted copy constructor + WellManager( WellManager const & ) = delete; + + /// default move constructor + WellManager( WellManager && ) = default; + + /// deleted assignment operator + WellManager & operator=( WellManager const & ) = delete; + + /// deleted move operator + WellManager & operator=( WellManager && ) = delete; + + virtual Group * createChild( string const & childKey, string const & childName ) override; + + /// Expand catalog for schema generation + virtual void expandObjectCatalogs() override; + + /** + * @brief name of the node manager in the object catalog + * @return string that contains the catalog name to generate a new NodeManager object through the object catalog. + */ + static string catalogName() { return "WellManager"; } + /** + * @copydoc PhysicsSolverBase::getCatalogName() + */ + string getCatalogName() const override { return catalogName(); } + + /** + * @brief Get a well solver for a given well element sub-region + * @param subRegion the well subRegion whose well solver is requested + * @return a reference to the well solver + */ + WellSolverBase & getWell( WellElementSubRegion const & subRegion ); + + /* PhysicsSolverBase interfaces */ + /** + * @brief function to perform setup for implicit timestep + * @param time_n the time at the beginning of the step + * @param dt the desired timestep + * @param domain the domain partition + * + * This function should contain any step level initialization required to perform an implicit + * step. + * + * @note This function must be overridden in the derived physics solver in order to use an implict + * solution method such as LinearImplicitStep() or NonlinearImplicitStep(). + */ + virtual void + implicitStepSetup( real64 const & time_n, + real64 const & dt, + DomainPartition & domain ) override; + +#if 0 + /** + * @brief function to assemble the linear system matrix and rhs + * @param time the time at the beginning of the step + * @param dt the desired timestep + * @param domain the domain partition + * @param dofManager degree-of-freedom manager associated with the linear system + * @param localMatrix the system matrix + * @param localRhs the system right-hand side vector + * + * This function assembles the residual and the jacobian of the residual wrt the primary + * variables. In a stand alone physics solver, this function will fill a single block in the + * block system. However the capability to query the block system structure for any coupled blocks + * may be implemented to fill in off diagonal blocks of the system to enable coupling between + * solvers. + * + * @note This function must be overridden in the derived physics solver in order to use an implict + * solution method such as LinearImplicitStep() or NonlinearImplicitStep(). + */ + virtual void + assembleSystem( real64 const time, + real64 const dt, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ); + + /** + * @brief calculate the norm of the global system residual + * @param time the time at the beginning of the step + * @param dt the desired timestep + * @param domain the domain partition + * @param dofManager degree-of-freedom manager associated with the linear system + * @param localRhs the system right-hand side vector + * @return norm of the residual + * + * This function returns the norm of global residual vector, which is suitable for comparison with + * a tolerance. + */ + virtual real64 + calculateResidualNorm( real64 const & time, + real64 const & dt, + DomainPartition const & domain, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs ); + /** + * @brief Function to check system solution for physical consistency and constraint violation + * @param domain the domain partition + * @param dofManager degree-of-freedom manager associated with the linear system + * @param localSolution the solution vector + * @param scalingFactor factor to scale the solution prior to application + * @return true if solution can be safely applied without violating physical constraints, false otherwise + * + * @note This function must be overridden in the derived physics solver in order to use an implict + * solution method such as LinearImplicitStep() or NonlinearImplicitStep(). + * + */ + virtual bool + checkSystemSolution( DomainPartition & domain, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor ); + + /** + * @brief Function to determine if the solution vector should be scaled back in order to maintain a known constraint. + * @param[in] domain The domain partition. + * @param[in] dofManager degree-of-freedom manager associated with the linear system + * @param[in] localSolution the solution vector + * @return The factor that should be used to scale the solution vector values when they are being applied. + */ + virtual real64 + scalingForSystemSolution( DomainPartition & domain, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution ); + + /** + * @brief Function to apply the solution vector to the state + * @param dofManager degree-of-freedom manager associated with the linear system + * @param localSolution the solution vector + * @param scalingFactor factor to scale the solution prior to application + * @param dt the timestep + * @param domain the domain partition + * + * This function performs 2 operations: + * 1) extract the solution vector for the "blockSystem" parameter, and applies the + * contents of the solution vector to the primary variable field data, + * 2) perform a synchronization of the primary field variable such that all ghosts are updated, + * + * The "scalingFactor" parameter allows for the scaled application of the solution vector. For + * instance, a line search may apply a negative scaling factor to remove part of the previously + * applied solution. + * + * @note This function must be overridden in the derived physics solver in order to use an implict + * solution method such as LinearImplicitStep() or NonlinearImplicitStep(). + * + */ + virtual void + applySystemSolution( DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor, + real64 const dt, + DomainPartition & domain ); + + + /** + * @brief Recompute all dependent quantities from primary variables (including constitutive models) + * @param domain the domain containing the mesh and fields + */ + virtual void updateState( DomainPartition & domain ); + + /** + * @brief perform cleanup for implicit timestep + * @param time the time at the beginning of the step + * @param dt the desired timestep + * @param domain the domain partition + * + * This function performs whatever tasks are required to complete an implicit timestep. For + * example, the acceptance of the solution will occur during this step, and deallocation of + * temporaries will be be performed in this function. + * + * @note This function must be overridden in the derived physics solver in order to use an implict + * solution method such as LinearImplicitStep() or NonlinearImplicitStep(). + */ + virtual void + implicitStepComplete( real64 const & time, + real64 const & dt, + DomainPartition & domain ) override; + +#endif +}; + +} + +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELL_MANAGER_HPP_ diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp index 9de04730e26..3e8d734c0e4 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp @@ -128,6 +128,12 @@ class WellSolverBase : public PhysicsSolverBase */ virtual localIndex numFluidPhases() const = 0; + /** + * @brief getter for the well associated to this subRegion + * @param subRegion the well subRegion whose controls are requested + * @return a reference to the well + */ + WellSolverBase & getWell( WellElementSubRegion const & subRegion ); /** * @brief getter for the well controls associated to this well subRegion * @param subRegion the well subRegion whose controls are requested From 30f529899bc0e3ba10e8303aa8621c4fd8328aa5 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 13 Jan 2026 07:48:09 -0800 Subject: [PATCH 50/71] convert a few well manager interfaces to demonstrate how a compo/singlephase well is called --- .../compositionalMultiphaseWell/bos.xml | 303 +++++++++++++++++ .../physicsSolvers/fluidFlow/CMakeLists.txt | 2 + .../wells/CompositionalMultiphaseWell.cpp | 233 +++++-------- .../wells/CompositionalMultiphaseWell.hpp | 29 +- .../fluidFlow/wells/SinglePhaseWell.cpp | 1 - .../fluidFlow/wells/SinglePhaseWell.hpp | 4 +- .../fluidFlow/wells/WellControls.cpp | 9 +- .../fluidFlow/wells/WellControls.hpp | 6 +- .../fluidFlow/wells/WellManager.cpp | 311 +++++++++++++++++- .../fluidFlow/wells/WellManager.hpp | 173 +++++++++- .../fluidFlow/wells/WellSolverBase.cpp | 26 +- .../fluidFlow/wells/WellSolverBase.hpp | 12 +- ...mpositionalMultiphaseReservoirAndWells.cpp | 1 - ...mpositionalMultiphaseReservoirAndWells.hpp | 6 +- .../CoupledReservoirAndWellsBase.cpp | 2 +- .../CoupledReservoirAndWellsBase.hpp | 4 +- .../SinglePhaseReservoirAndWells.hpp | 6 +- 17 files changed, 922 insertions(+), 206 deletions(-) create mode 100644 inputFiles/compositionalMultiphaseWell/bos.xml diff --git a/inputFiles/compositionalMultiphaseWell/bos.xml b/inputFiles/compositionalMultiphaseWell/bos.xml new file mode 100644 index 00000000000..dd692e88969 --- /dev/null +++ b/inputFiles/compositionalMultiphaseWell/bos.xml @@ -0,0 +1,303 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt index 711defe6b68..aaa73ca1d6a 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt +++ b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt @@ -138,6 +138,7 @@ set( fluidFlowSolvers_headers wells/WellPhaseVolumeRateConstraint.hpp wells/WellLiquidRateConstraint.hpp wells/WellSolverBase.hpp + wells/WellManager.hpp wells/WellSolverBaseFields.hpp wells/LogLevelsInfo.hpp wells/kernels/SinglePhaseWellKernels.hpp @@ -184,6 +185,7 @@ set( fluidFlowSolvers_sources wells/WellPhaseVolumeRateConstraint.cpp wells/WellLiquidRateConstraint.cpp wells/WellSolverBase.cpp + wells/WellManager.cpp proppantTransport/ProppantTransport.cpp proppantTransport/ProppantTransportKernels.cpp ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 3515711e05c..f6d32af2147 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -147,27 +147,17 @@ void CompositionalMultiphaseWell::postInputInitialization() ": The maximum relative change in component density must be larger than 0.0" ); } -void CompositionalMultiphaseWell::registerDataOnMesh( Group & meshBodies ) +void CompositionalMultiphaseWell::registerWellDataOnMesh( WellElementSubRegion & subRegion ) { - WellSolverBase::registerDataOnMesh( meshBodies ); - + // WellSolverBase::registerDataOnMesh( meshBodies ); replaced by following 2 lines + setConstitutiveNamesCallSuper( subRegion ); + setConstitutiveNames( subRegion ); DomainPartition const & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); ConstitutiveManager const & cm = domain.getConstitutiveManager(); - - forDiscretizationOnMeshTargets( meshBodies, [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) + if( m_referenceFluidModelName.empty() ) { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - if( m_referenceFluidModelName.empty() ) - { - m_referenceFluidModelName = getConstitutiveName< MultiFluidBase >( subRegion ); - } - } ); - } ); + m_referenceFluidModelName = getConstitutiveName< MultiFluidBase >( subRegion ); + } // 1. Set key dimensions of the problem // Empty check needed to avoid errors when running in schema generation mode. @@ -182,112 +172,99 @@ void CompositionalMultiphaseWell::registerDataOnMesh( Group & meshBodies ) // 1 pressure + NC compositions + temp if thermal m_numDofPerResElement = isThermal() ? m_numComponents + 2 : m_numComponents + 1; - // loop over the wells - forDiscretizationOnMeshTargets( meshBodies, [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - ElementRegionManager & elemManager = mesh.getElemManager(); + string const & fluidName = getConstitutiveName< MultiFluidBase >( subRegion ); + MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - string const & fluidName = getConstitutiveName< MultiFluidBase >( subRegion ); - MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); + // The resizing of the arrays needs to happen here, before the call to initializePreSubGroups, + // to make sure that the dimensions are properly set before the timeHistoryOutput starts its initialization. - // The resizing of the arrays needs to happen here, before the call to initializePreSubGroups, - // to make sure that the dimensions are properly set before the timeHistoryOutput starts its initialization. + subRegion.registerField< well::globalCompDensity >( getName() ). + reference().resizeDimension< 1 >( m_numComponents ); + subRegion.registerField< well::globalCompDensity_n >( getName() ). + reference().resizeDimension< 1 >( m_numComponents ); - subRegion.registerField< well::globalCompDensity >( getName() ). - reference().resizeDimension< 1 >( m_numComponents ); - subRegion.registerField< well::globalCompDensity_n >( getName() ). - reference().resizeDimension< 1 >( m_numComponents ); + subRegion.registerField< well::mixtureConnectionRate >( getName() ); + subRegion.registerField< well::mixtureConnectionRate_n >( getName() ); - subRegion.registerField< well::mixtureConnectionRate >( getName() ); - subRegion.registerField< well::mixtureConnectionRate_n >( getName() ); + subRegion.registerField< well::globalCompFraction >( getName() ). + setDimLabels( 1, fluid.componentNames() ). + reference().resizeDimension< 1 >( m_numComponents ); + subRegion.registerField< well::dGlobalCompFraction_dGlobalCompDensity >( getName() ). + reference().resizeDimension< 1, 2 >( m_numComponents, m_numComponents ); - subRegion.registerField< well::globalCompFraction >( getName() ). - setDimLabels( 1, fluid.componentNames() ). - reference().resizeDimension< 1 >( m_numComponents ); - subRegion.registerField< well::dGlobalCompFraction_dGlobalCompDensity >( getName() ). - reference().resizeDimension< 1, 2 >( m_numComponents, m_numComponents ); + subRegion.registerField< well::phaseVolumeFraction >( getName() ). + setDimLabels( 1, fluid.phaseNames() ). + reference().resizeDimension< 1 >( m_numPhases ); + subRegion.registerField< well::dPhaseVolumeFraction >( getName() ). + reference().resizeDimension< 1, 2 >( m_numPhases, m_numComponents + 2 ); // dP, dT, dC - subRegion.registerField< well::phaseVolumeFraction >( getName() ). - setDimLabels( 1, fluid.phaseNames() ). - reference().resizeDimension< 1 >( m_numPhases ); - subRegion.registerField< well::dPhaseVolumeFraction >( getName() ). - reference().resizeDimension< 1, 2 >( m_numPhases, m_numComponents + 2 ); // dP, dT, dC + subRegion.registerField< well::totalMassDensity >( getName() ); + subRegion.registerField< well::dTotalMassDensity >( getName() ). + reference().resizeDimension< 1 >( m_numComponents +2 ); // dP, dT, dC - subRegion.registerField< well::totalMassDensity >( getName() ); - subRegion.registerField< well::dTotalMassDensity >( getName() ). - reference().resizeDimension< 1 >( m_numComponents +2 ); // dP, dT, dC + subRegion.registerField< well::phaseVolumeFraction_n >( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); - subRegion.registerField< well::phaseVolumeFraction_n >( getName() ). - reference().resizeDimension< 1 >( m_numPhases ); + subRegion.registerField< well::pressureScalingFactor >( getName() ); + subRegion.registerField< well::temperatureScalingFactor >( getName() ); + subRegion.registerField< well::globalCompDensityScalingFactor >( getName() ); - subRegion.registerField< well::pressureScalingFactor >( getName() ); - subRegion.registerField< well::temperatureScalingFactor >( getName() ); - subRegion.registerField< well::globalCompDensityScalingFactor >( getName() ); + PerforationData & perforationData = *subRegion.getPerforationData(); + perforationData.registerField< well::compPerforationRate >( getName() ). + reference().resizeDimension< 1 >( m_numComponents ); - PerforationData & perforationData = *subRegion.getPerforationData(); - perforationData.registerField< well::compPerforationRate >( getName() ). - reference().resizeDimension< 1 >( m_numComponents ); + perforationData.registerField< well::dCompPerforationRate >( getName() ). + reference().resizeDimension< 1, 2, 3 >( 2, m_numComponents, m_numComponents+ 2 ); + if( fluid.isThermal() ) + { + perforationData.registerField< well::energyPerforationFlux >( getName() ); + perforationData.registerField< well::dEnergyPerforationFlux >( getName() ). + reference().resizeDimension< 1, 2 >( 2, m_numComponents+2 ); + } - perforationData.registerField< well::dCompPerforationRate >( getName() ). - reference().resizeDimension< 1, 2, 3 >( 2, m_numComponents, m_numComponents+ 2 ); - if( fluid.isThermal() ) - { - perforationData.registerField< well::energyPerforationFlux >( getName() ); - perforationData.registerField< well::dEnergyPerforationFlux >( getName() ). - reference().resizeDimension< 1, 2 >( 2, m_numComponents+2 ); - } + registerWrapper< real64 >( viewKeyStruct::currentBHPString() ); - WellControls & wellControls = getWellControls( subRegion ); - wellControls.registerWrapper< real64 >( viewKeyStruct::currentBHPString() ); + registerWrapper< array1d< real64 > >( viewKeyStruct::currentPhaseVolRateString() ). + setSizedFromParent( 0 ). + reference().resizeDimension< 0 >( m_numPhases ); - wellControls.registerWrapper< array1d< real64 > >( viewKeyStruct::currentPhaseVolRateString() ). - setSizedFromParent( 0 ). - reference().resizeDimension< 0 >( m_numPhases ); + registerWrapper< real64 >( viewKeyStruct::massDensityString() ); - wellControls.registerWrapper< real64 >( viewKeyStruct::massDensityString() ); + registerWrapper< real64 >( viewKeyStruct::currentTotalVolRateString() ); - wellControls.registerWrapper< real64 >( viewKeyStruct::currentTotalVolRateString() ); + registerWrapper< real64 >( viewKeyStruct::massDensityString() ); - wellControls.registerWrapper< real64 >( viewKeyStruct::massDensityString() ); + registerWrapper< real64 >( viewKeyStruct::currentMassRateString() ); - 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() ) + { + string const fileName = GEOS_FMT( "{}/{}.csv", m_ratesOutputDir, getName() ); + string const massUnit = m_useMass ? "kg" : "mol"; + integer const useSurfaceConditions = this->useSurfaceConditions(); + string const conditionKey = useSurfaceConditions ? "surface" : "reservoir"; + string const unitKey = useSurfaceConditions ? "s" : "r"; + integer const numPhase = m_numPhases; + integer const numComp = m_numComponents; + // format: time,bhp,total_rate,total_vol_rate,phase0_vol_rate,phase1_vol_rate,... + makeDirsForPath( m_ratesOutputDir ); + GEOS_LOG( GEOS_FMT( "{}: Rates CSV generated at {}", getName(), fileName ) ); + std::ofstream outputFile( fileName ); + outputFile << "Time [s],dt[s],BHP [Pa],Total rate [" << massUnit << "/s],Total " << conditionKey << " volumetric rate [" << unitKey << "m3/s]"; + for( integer ip = 0; ip < numPhase; ++ip ) + { + outputFile << ",Phase" << ip << " " << conditionKey << " volumetric rate [" << unitKey << "m3/s]"; + } + for( integer ic = 0; ic < numComp; ++ic ) + { + outputFile << ",Component" << ic << " rate [" << massUnit << "/s]"; + } + outputFile << std::endl; + outputFile.close(); + } - // write rates output header - // the rank that owns the reference well element is responsible - if( m_writeCSV > 0 && subRegion.isLocallyOwned() ) - { - string const fileName = GEOS_FMT( "{}/{}.csv", m_ratesOutputDir, wellControls.getName() ); - string const massUnit = m_useMass ? "kg" : "mol"; - integer const useSurfaceConditions = wellControls.useSurfaceConditions(); - string const conditionKey = useSurfaceConditions ? "surface" : "reservoir"; - string const unitKey = useSurfaceConditions ? "s" : "r"; - integer const numPhase = m_numPhases; - integer const numComp = m_numComponents; - // format: time,bhp,total_rate,total_vol_rate,phase0_vol_rate,phase1_vol_rate,... - makeDirsForPath( m_ratesOutputDir ); - GEOS_LOG( GEOS_FMT( "{}: Rates CSV generated at {}", getName(), fileName ) ); - std::ofstream outputFile( fileName ); - outputFile << "Time [s],dt[s],BHP [Pa],Total rate [" << massUnit << "/s],Total " << conditionKey << " volumetric rate [" << unitKey << "m3/s]"; - for( integer ip = 0; ip < numPhase; ++ip ) - { - outputFile << ",Phase" << ip << " " << conditionKey << " volumetric rate [" << unitKey << "m3/s]"; - } - for( integer ic = 0; ic < numComp; ++ic ) - { - outputFile << ",Component" << ic << " rate [" << massUnit << "/s]"; - } - outputFile << std::endl; - outputFile.close(); - } - } ); - } ); } @@ -339,15 +316,18 @@ void compareMulticomponentModels( MODEL1_TYPE const & lhs, MODEL2_TYPE const & r * @brief Checks if the WellControls parameters are within the fluid tables ranges * @param fluid the fluid to check */ -void CompositionalMultiphaseWell::validateWellControlsForFluid( WellControls const & wellControls, - MultiFluidBase const & fluid ) const +void CompositionalMultiphaseWell::validateFluidModel( + constitutive::MultiFluidBase const & fluid, constitutive::MultiFluidBase const & referenceFluid ) const { - if( wellControls.useSurfaceConditions() ) + + compareMultiphaseModels( fluid, referenceFluid ); + compareMulticomponentModels( fluid, referenceFluid ); + if( useSurfaceConditions() ) { try { - real64 const & surfaceTemp = wellControls.getSurfaceTemperature(); - real64 const & surfacePres = wellControls.getSurfacePressure(); + real64 const & surfaceTemp = getSurfaceTemperature(); + real64 const & surfacePres = getSurfacePressure(); fluid.checkTablesParameters( surfacePres, surfaceTemp ); } catch( SimulationError const & ex ) { @@ -360,37 +340,6 @@ void CompositionalMultiphaseWell::validateWellControlsForFluid( WellControls con } } -void CompositionalMultiphaseWell::validateConstitutiveModels( DomainPartition const & domain ) const -{ - GEOS_MARK_FUNCTION; - - ConstitutiveManager const & cm = domain.getConstitutiveManager(); - CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); - string const referenceFluidName = flowSolver.referenceFluidModelName(); - MultiFluidBase const & referenceFluid = cm.getConstitutiveRelation< MultiFluidBase >( m_referenceFluidModelName ); - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel const & mesh, - string_array const & regionNames ) - { - - mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, - WellElementSubRegion const & subRegion ) - { - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); - compareMultiphaseModels( fluid, referenceFluid ); - compareMulticomponentModels( fluid, referenceFluid ); - - WellControls const & wellControls = getWellControls( subRegion ); - validateWellControlsForFluid( wellControls, fluid ); - } ); - - } ); -} - - - void CompositionalMultiphaseWell::validateWellConstraints( real64 const & time_n, real64 const & GEOS_UNUSED_PARAM( dt ), WellElementSubRegion const & subRegion ) @@ -439,9 +388,9 @@ void CompositionalMultiphaseWell::initializePostSubGroups() { WellSolverBase::initializePostSubGroups(); - DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); + //DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); - validateConstitutiveModels( domain ); + // tjbvalidateConstitutiveModels( domain ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp index 6ad93ec3f44..be387148f39 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp @@ -22,11 +22,11 @@ #include "constitutive/fluid/multifluid/Layouts.hpp" #include "constitutive/relativePermeability/Layouts.hpp" -#include "physicsSolvers/fluidFlow/wells/WellSolverBase.hpp" + #include "physicsSolvers/fluidFlow/CompositionalMultiphaseBase.hpp" #include "physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp" - +#include "physicsSolvers/fluidFlow/wells/WellSolverBase.hpp" namespace geos { @@ -59,8 +59,8 @@ class CompositionalMultiphaseWell : public WellSolverBase /// deleted copy constructor CompositionalMultiphaseWell( CompositionalMultiphaseWell const & ) = delete; - /// default move constructor - CompositionalMultiphaseWell( CompositionalMultiphaseWell && ) = default; + /// deleted move constructor + CompositionalMultiphaseWell( CompositionalMultiphaseWell && ) = delete; /// deleted assignment operator CompositionalMultiphaseWell & operator=( CompositionalMultiphaseWell const & ) = delete; @@ -83,7 +83,7 @@ class CompositionalMultiphaseWell : public WellSolverBase */ string getCatalogName() const override { return catalogName(); } - virtual void registerDataOnMesh( Group & meshBodies ) override; + void registerWellDataOnMesh( WellElementSubRegion & subRegion ); /** @@ -393,24 +393,17 @@ class CompositionalMultiphaseWell : public WellSolverBase void saveState( WellElementSubRegion & subRegion ); virtual void postRestartInitialization() override final; - /* - * @brief Utility function that checks the consistency of the constitutive models - * @param[in] domain the domain partition + + /** + * @brief Checks fluild model compatibility and validity + * @param[in] fluid the fluid to check + * @param[in] referenceFluid the reference fluid model * @detail * This function will produce an error if one of the well constitutive models * is incompatible with the corresponding models in reservoir * regions connected to that particular well. */ - void validateConstitutiveModels( DomainPartition const & domain ) const; - - /** - * @brief Checks if the WellControls parameters are within the fluid tables ranges - * @param fluid the fluid to check - */ - void validateWellControlsForFluid( WellControls const & wellControls, - constitutive::MultiFluidBase const & fluid ) const; - - + void validateFluidModel( constitutive::MultiFluidBase const & fluid, constitutive::MultiFluidBase const & referenceFluid )const; /** * @brief Make sure that the well constraints are compatible * @param time_n the time at the beginning of the time step diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index 7ddc8536125..eb9f738efdc 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -37,7 +37,6 @@ #include "physicsSolvers/fluidFlow/wells/WellFields.hpp" #include "physicsSolvers/fluidFlow/wells/WellSolverBaseFields.hpp" #include "physicsSolvers/fluidFlow/wells/SinglePhaseWellFields.hpp" -#include "physicsSolvers/fluidFlow/wells/WellControls.hpp" #include "physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.hpp" #include "physicsSolvers/fluidFlow/wells/kernels/ThermalSinglePhaseWellKernels.hpp" #include "physicsSolvers/fluidFlow/wells/kernels/SinglePhasePerforationFluxKernels.hpp" diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp index fb22dd9feb5..ce5ff5d8bec 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp @@ -20,7 +20,7 @@ #ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_SINGLEPHASEWELL_HPP_ #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_SINGLEPHASEWELL_HPP_ -#include "WellSolverBase.hpp" +#include "physicsSolvers/fluidFlow/wells/WellSolverBase.hpp" #include "constitutive/fluid/singlefluid/SingleFluidLayouts.hpp" @@ -63,7 +63,7 @@ class SinglePhaseWell : public WellSolverBase SinglePhaseWell( SinglePhaseWell const & ) = delete; /// default move constructor - SinglePhaseWell( SinglePhaseWell && ) = default; + SinglePhaseWell( SinglePhaseWell && ) = delete; /// deleted assignment operator SinglePhaseWell & operator=( SinglePhaseWell const & ) = delete; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index 382dcc5d109..af5b94ed42c 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -30,7 +30,7 @@ namespace geos using namespace dataRepository; WellControls::WellControls( string const & name, Group * const parent ) - : Group( name, parent ), + : PhysicsSolverBase( name, parent ), m_type( Type::PRODUCER ), m_inputControl( Control::UNINITIALIZED ), m_currentControl( Control::UNINITIALIZED ), // tjb remove @@ -112,6 +112,11 @@ WellControls::~WellControls() Group * WellControls::createChild( string const & childKey, string const & childName ) { + Group * baseChild = PhysicsSolverBase::createChild( childKey, childName ); + if( baseChild != nullptr ) + { + return baseChild; + } GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); ////const auto childTypes = { viewKeyStruct::perforationString() }; //GEOS_ERROR_IF( childKey != viewKeyStruct::perforationString(), @@ -211,7 +216,7 @@ TableFunction * createWellTable( string const & tableName, void WellControls::postInputInitialization() { - + PhysicsSolverBase::postInputInitialization(); // 0) Assign the value of the current well control // When the simulation starts from a restart file, we don't want to use the inputControl, // because the control may have switched in the simulation that generated the restart diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp index 625891c00ff..2ad9ca3f7e4 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp @@ -20,7 +20,7 @@ #ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONTROLS_HPP #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONTROLS_HPP - +#include "physicsSolvers/PhysicsSolverBase.hpp" #include "common/format/EnumStrings.hpp" #include "dataRepository/Group.hpp" #include "functions/TableFunction.hpp" @@ -35,6 +35,8 @@ #include "physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.hpp" #include "constitutive/fluid/multifluid/MultiFluidBase.hpp" #include "constitutive/fluid/singlefluid/SingleFluidBase.hpp" + + namespace geos { namespace dataRepository @@ -50,7 +52,7 @@ static constexpr auto wellControls = "WellControls"; * @class WellControls * @brief This class describes the controls used to operate a well. */ -class WellControls : public dataRepository::Group +class WellControls : public PhysicsSolverBase { public: diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp index 44de4deb621..7ba11d60d11 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp @@ -37,12 +37,32 @@ using namespace dataRepository; using namespace fields; WellManager::WellManager( string const & name, - Group * const parent ) - : PhysicsSolverBase( name, parent ) - + Group * const parent ) + : PhysicsSolverBase( name, parent ), + m_useMass( false ), + m_useTotalMassEquation( 1 ), + m_isThermal( 0 ), + m_isCompositional( true ) { this->getWrapper< string >( viewKeyStruct::discretizationString() ). - setInputFlag( InputFlags::FALSE ); + setInputFlag( InputFlags::FALSE ); + + registerWrapper( viewKeyStruct::isThermalString(), &m_isThermal ). + setApplyDefaultValue( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Flag indicating whether the problem is thermal or not." ); + + + this->registerWrapper( viewKeyStruct::useMassFlagString(), &m_useMass ). + setApplyDefaultValue( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Use mass formulation instead of molar" ); + + this->registerWrapper( viewKeyStruct::useTotalMassEquationString(), &m_useTotalMassEquation ). + setApplyDefaultValue( 1 ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Use total mass equation" ); + } Group * WellManager::createChild( string const & childKey, string const & childName ) { @@ -57,10 +77,12 @@ Group * WellManager::createChild( string const & childKey, string const & childN getDataContext() ); if( childKey == keys::compositionalMultiphaseWell ) { + setCompositional( true ); return ®isterGroup< CompositionalMultiphaseWell >( childName ); } else if( childKey == keys::singlePhaseWell ) { + setCompositional( false ); return ®isterGroup< SinglePhaseWell >( childName ); } else @@ -75,14 +97,202 @@ void WellManager::expandObjectCatalogs() createChild( keys::compositionalMultiphaseWell, keys::compositionalMultiphaseWell ); createChild( keys::singlePhaseWell, keys::singlePhaseWell ); } + +void WellManager::registerDataOnMesh( Group & meshBodies ) +{ + if( isCompositional() ) + { + + forDiscretizationOnMeshTargets( meshBodies, [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + + ElementRegionManager & elemManager = mesh.getElemManager(); + + elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + CompositionalMultiphaseWell & well = getCompositionalMultiphaseWell( subRegion ); + well.registerWellDataOnMesh( subRegion ); + m_numFluidPhases = well.numFluidPhases(); + m_numFluidComponents = well.numFluidComponents(); + } ); + } ); + // 1. Set key dimensions of the problem + // Empty check needed to avoid errors when running in schema generation mode. + + // 1 pressure + NC compositions + 1 connectionRate + temp if thermal + m_numDofPerWellElement = isThermal() ? m_numFluidComponents + 3 : m_numFluidComponents + 2; + // 1 pressure + NC compositions + temp if thermal + m_numDofPerResElement = isThermal() ? m_numFluidComponents + 2 : m_numFluidComponents + 1; + + } + else + { + // Single phase registration can be added here in the future + } +#if 0 + DomainPartition const & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); + ConstitutiveManager const & cm = domain.getConstitutiveManager(); + + forDiscretizationOnMeshTargets( meshBodies, [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + if( m_referenceFluidModelName.empty() ) + { + m_referenceFluidModelName = getConstitutiveName< MultiFluidBase >( subRegion ); + } + } ); + } ); + + // 1. Set key dimensions of the problem + // Empty check needed to avoid errors when running in schema generation mode. + if( !m_referenceFluidModelName.empty() ) + { + MultiFluidBase const & fluid0 = cm.getConstitutiveRelation< MultiFluidBase >( m_referenceFluidModelName ); + m_numPhases = fluid0.numFluidPhases(); + m_numComponents = fluid0.numFluidComponents(); + } + // 1 pressure + NC compositions + 1 connectionRate + temp if thermal + m_numDofPerWellElement = isThermal() ? m_numComponents + 3 : m_numComponents + 2; + // 1 pressure + NC compositions + temp if thermal + m_numDofPerResElement = isThermal() ? m_numComponents + 2 : m_numComponents + 1; + + // loop over the wells + forDiscretizationOnMeshTargets( meshBodies, [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + + ElementRegionManager & elemManager = mesh.getElemManager(); + + elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + string const & fluidName = getConstitutiveName< MultiFluidBase >( subRegion ); + MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); + + // The resizing of the arrays needs to happen here, before the call to initializePreSubGroups, + // to make sure that the dimensions are properly set before the timeHistoryOutput starts its initialization. + + subRegion.registerField< well::globalCompDensity >( getName() ). + reference().resizeDimension< 1 >( m_numComponents ); + subRegion.registerField< well::globalCompDensity_n >( getName() ). + reference().resizeDimension< 1 >( m_numComponents ); + + subRegion.registerField< well::mixtureConnectionRate >( getName() ); + subRegion.registerField< well::mixtureConnectionRate_n >( getName() ); + + subRegion.registerField< well::globalCompFraction >( getName() ). + setDimLabels( 1, fluid.componentNames() ). + reference().resizeDimension< 1 >( m_numComponents ); + subRegion.registerField< well::dGlobalCompFraction_dGlobalCompDensity >( getName() ). + reference().resizeDimension< 1, 2 >( m_numComponents, m_numComponents ); + + subRegion.registerField< well::phaseVolumeFraction >( getName() ). + setDimLabels( 1, fluid.phaseNames() ). + reference().resizeDimension< 1 >( m_numPhases ); + subRegion.registerField< well::dPhaseVolumeFraction >( getName() ). + reference().resizeDimension< 1, 2 >( m_numPhases, m_numComponents + 2 ); // dP, dT, dC + + subRegion.registerField< well::totalMassDensity >( getName() ); + subRegion.registerField< well::dTotalMassDensity >( getName() ). + reference().resizeDimension< 1 >( m_numComponents +2 ); // dP, dT, dC + + subRegion.registerField< well::phaseVolumeFraction_n >( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); + + subRegion.registerField< well::pressureScalingFactor >( getName() ); + subRegion.registerField< well::temperatureScalingFactor >( getName() ); + subRegion.registerField< well::globalCompDensityScalingFactor >( getName() ); + + PerforationData & perforationData = *subRegion.getPerforationData(); + perforationData.registerField< well::compPerforationRate >( getName() ). + reference().resizeDimension< 1 >( m_numComponents ); + + perforationData.registerField< well::dCompPerforationRate >( getName() ). + reference().resizeDimension< 1, 2, 3 >( 2, m_numComponents, m_numComponents+ 2 ); + if( fluid.isThermal() ) + { + perforationData.registerField< well::energyPerforationFlux >( getName() ); + perforationData.registerField< well::dEnergyPerforationFlux >( getName() ). + reference().resizeDimension< 1, 2 >( 2, m_numComponents+2 ); + } + + WellControls & wellControls = getWellControls( subRegion ); + wellControls.registerWrapper< real64 >( viewKeyStruct::currentBHPString() ); + + wellControls.registerWrapper< array1d< real64 > >( viewKeyStruct::dCurrentBHPString() ). + setSizedFromParent( 0 ). + reference().resizeDimension< 0 >( m_numComponents + 2 ); // dP, dT, dC + + wellControls.registerWrapper< array1d< real64 > >( viewKeyStruct::currentPhaseVolRateString() ). + setSizedFromParent( 0 ). + reference().resizeDimension< 0 >( m_numPhases ); + + wellControls.registerWrapper< array2d< real64 > >( viewKeyStruct::dCurrentPhaseVolRateString() ). + setSizedFromParent( 0 ). + reference().resizeDimension< 0, 1 >( m_numPhases, m_numComponents + 3 ); // dP, dT, dC, dQ + + wellControls.registerWrapper< real64 >( viewKeyStruct::massDensityString() ); + + wellControls.registerWrapper< real64 >( viewKeyStruct::currentTotalVolRateString() ); + wellControls.registerWrapper< array1d< real64 > >( viewKeyStruct::dCurrentTotalVolRateString() ). + setSizedFromParent( 0 ). + reference().resizeDimension< 0 >( m_numComponents + 3 ); // dP, dT, dC dQ + + 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() ) + { + string const fileName = GEOS_FMT( "{}/{}.csv", m_ratesOutputDir, wellControls.getName() ); + string const massUnit = m_useMass ? "kg" : "mol"; + integer const useSurfaceConditions = wellControls.useSurfaceConditions(); + string const conditionKey = useSurfaceConditions ? "surface" : "reservoir"; + string const unitKey = useSurfaceConditions ? "s" : "r"; + integer const numPhase = m_numPhases; + integer const numComp = m_numComponents; + // format: time,bhp,total_rate,total_vol_rate,phase0_vol_rate,phase1_vol_rate,... + makeDirsForPath( m_ratesOutputDir ); + GEOS_LOG( GEOS_FMT( "{}: Rates CSV generated at {}", getName(), fileName ) ); + std::ofstream outputFile( fileName ); + outputFile << "Time [s],dt[s],BHP [Pa],Total rate [" << massUnit << "/s],Total " << conditionKey << " volumetric rate [" << unitKey << "m3/s]"; + for( integer ip = 0; ip < numPhase; ++ip ) + { + outputFile << ",Phase" << ip << " " << conditionKey << " volumetric rate [" << unitKey << "m3/s]"; + } + for( integer ic = 0; ic < numComp; ++ic ) + { + outputFile << ",Component" << ic << " rate [" << massUnit << "/s]"; + } + outputFile << std::endl; + outputFile.close(); + } + } ); + } ); +#endif +} + WellSolverBase & WellManager::getWell( WellElementSubRegion const & subRegion ) { return this->getGroup< WellSolverBase >( subRegion.getWellControlsName()); } void WellManager::implicitStepSetup( real64 const & time_n, - real64 const & dt, - DomainPartition & domain ) + real64 const & dt, + DomainPartition & domain ) { forDiscretizationOnMeshTargets ( domain.getMeshBodies(), [&] ( string const &, @@ -103,5 +313,94 @@ void WellManager::implicitStepSetup( real64 const & time_n, ; } ); } + +localIndex WellManager::numDofPerWellElement() const +{ + return m_numDofPerWellElement; +} + +localIndex WellManager::numDofPerResElement() const +{ + return m_numDofPerResElement; +} +integer WellManager::isThermal() const +{ + return m_isThermal; +} + +string WellManager::wellElementDofName() const +{ + return viewKeyStruct::dofFieldString(); +} + +string WellManager::resElementDofName() const +{ + return "reservoirCouplingVars"; +} + +localIndex WellManager::numFluidComponents() const +{ + return m_numFluidComponents; +} + +localIndex WellManager::numFluidPhases() const +{ + return m_numFluidPhases; +} +WellControls & WellManager::getWellControls( WellElementSubRegion const & subRegion ) +{ + return this->getGroup< WellControls >( subRegion.getWellControlsName()); +} + +WellControls const & WellManager::getWellControls( WellElementSubRegion const & subRegion ) const +{ + return this->getGroup< WellControls >( subRegion.getWellControlsName()); +} + +CompositionalMultiphaseWell & WellManager::getCompositionalMultiphaseWell( WellElementSubRegion const & subRegion ) +{ + return this->getGroup< CompositionalMultiphaseWell >( subRegion.getWellControlsName()); +} + +CompositionalMultiphaseWell const & WellManager::getCompositionalMultiphaseWell( WellElementSubRegion const & subRegion ) const +{ + return this->getGroup< CompositionalMultiphaseWell >( subRegion.getWellControlsName()); +} +void WellManager::initializePostSubGroups() +{ +#if 0 + GEOS_MARK_FUNCTION; + // Validate constitutive models + if( isCompositional() ) + { + DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); + constitutive::ConstitutiveManager const & cm = domain.getConstitutiveManager(); + CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); + string const referenceFluidName = flowSolver.referenceFluidModelName(); + constitutive::MultiFluidBase const & referenceFluid = cm.getConstitutiveRelation< constitutive::MultiFluidBase >( m_referenceFluidModelName ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel const & mesh, + string_array const & regionNames ) + { + + mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, + WellElementSubRegion const & subRegion ) + { + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + constitutive::MultiFluidBase const & fluid = getConstitutiveModel< constitutive::MultiFluidBase >( subRegion, fluidName ); + WellControls const & wellControls = getWellControls( subRegion ); + wellControls.validateFluidModel( fluid, referenceFluid ); + } ); + + } ); + } + else + { + // Single phase validation can be added here in the future + } +#endif +} + REGISTER_CATALOG_ENTRY( PhysicsSolverBase, WellManager, string const &, Group * const ) } // namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp index eb115781edf..b2c04666266 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp @@ -22,7 +22,7 @@ #include "physicsSolvers/PhysicsSolverBase.hpp" #include "physicsSolvers/fluidFlow/wells/WellSolverBase.hpp" - +#include "physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp" namespace geos { @@ -57,7 +57,7 @@ class WellManager : public PhysicsSolverBase * @param parent the parent group of this instantiation of Group */ WellManager( const string & name, - Group * const parent ); + Group * const parent ); /// default destructor virtual ~WellManager() override = default; @@ -82,6 +82,42 @@ class WellManager : public PhysicsSolverBase /// Expand catalog for schema generation virtual void expandObjectCatalogs() override; + /** + * @brief setter for the name of the flow solver (needed to use the flow kernels like UpdateFluid) + * @param name the name of the flow solver + */ + void setFlowSolverName( string const & name ) { m_flowSolverName = name; } + + /** + * @brief setter for compositional flag + * @param compositional the compositional flag + */ + void setCompositional( bool const & isCompositional ) { m_isCompositional = isCompositional; } + + /** + * @brief getter for compositional flag + * @return the compositional flag + */ + bool isCompositional() const { return m_isCompositional; } + + /** + * @brief Utility function to keep the well variables during a time step (used in + * poromechanics simulations) + * @param[in] keepVariablesConstantDuringInitStep flag to tell the solver to freeze its + * primary variables during a time step + * @detail This function is meant to be called by a specific task before/after the + * initialization step + */ + void setKeepVariablesConstantDuringInitStep( bool const keepVariablesConstantDuringInitStep ) + { m_keepVariablesConstantDuringInitStep = keepVariablesConstantDuringInitStep; } + + /** + * @brief getter for the name of the flow solver (used in UpdateState) + * @return a string containing the name of the flow solver + */ + string const & getFlowSolverName() const { return m_flowSolverName; } + + /** * @brief name of the node manager in the object catalog * @return string that contains the catalog name to generate a new NodeManager object through the object catalog. @@ -92,6 +128,7 @@ class WellManager : public PhysicsSolverBase */ string getCatalogName() const override { return catalogName(); } + virtual void registerDataOnMesh( Group & meshBodies ) override; /** * @brief Get a well solver for a given well element sub-region * @param subRegion the well subRegion whose well solver is requested @@ -99,6 +136,94 @@ class WellManager : public PhysicsSolverBase */ WellSolverBase & getWell( WellElementSubRegion const & subRegion ); + /** + * @brief get the name of DOF defined on well elements + * @return name of the DOF field used by derived solver type + */ + string wellElementDofName() const; + + struct viewKeyStruct : PhysicsSolverBase::viewKeyStruct + { + static constexpr char const * dofFieldString() { return "wellVars"; } + static constexpr char const * isThermalString() { return "isThermal"; } + static constexpr char const * useMassFlagString() {return "useMass"; } + + static constexpr char const * useTotalMassEquationString() { return "useTotalMassEquation"; } + + }; + + /** + * @brief getter for the number of degrees of freedom per well element + * @return the number of dofs + */ + localIndex numDofPerWellElement() const; + + /** + * @brief getter for the number of degrees of freedom per mesh element + * @return the number of dofs + */ + localIndex numDofPerResElement() const; + + /** + * @brief getter for iso/thermal switch + * @return True if thermal + */ + integer isThermal() const; + + + /** + * @brief get the name of DOF defined on well elements + * @return name of the DOF field used by derived solver type + */ + virtual string resElementDofName() const; + + /** + * @brief const getter for the number of fluid components + * @return the number of fluid components + */ + virtual localIndex numFluidComponents() const; + + /** + * @brief const getter for the number of fluid phases + * @return the number of fluid phases + */ + virtual localIndex numFluidPhases() const; + + /** + * @brief const getter for well total mass equation usage + * @return true if total mass equation is used + */ + integer useTotalMassEquation() const { return m_useTotalMassEquation; } + + /** + * @brief getter for the well controls associated to this well subRegion + * @param subRegion the well subRegion whose controls are requested + * @return a reference to the controls + */ + WellControls & getWellControls( WellElementSubRegion const & subRegion ); + + /** + * @brief const getter for the well controls associated to this well subRegion + * @param subRegion the well subRegion whose controls are requested + * @return a reference to the const controls + */ + WellControls const & getWellControls( WellElementSubRegion const & subRegion ) const; + + /** + * @brief getter for the compositional multiphase well associated to this well subRegion + * @param subRegion the well subRegion whose controls are requested + * @return a reference to the well + */ + CompositionalMultiphaseWell & getCompositionalMultiphaseWell( WellElementSubRegion const & subRegion ); + + /** + * @brief const getter for the compositional multiphase well associated to this well subRegion + * @param subRegion the well subRegion whose controls are requested + * @return a reference to the const well + */ + CompositionalMultiphaseWell const & getCompositionalMultiphaseWell( WellElementSubRegion const & subRegion ) const; + + /* PhysicsSolverBase interfaces */ /** * @brief function to perform setup for implicit timestep @@ -118,7 +243,7 @@ class WellManager : public PhysicsSolverBase DomainPartition & domain ) override; #if 0 - /** + /** * @brief function to assemble the linear system matrix and rhs * @param time the time at the beginning of the step * @param dt the desired timestep @@ -245,7 +370,47 @@ class WellManager : public PhysicsSolverBase real64 const & dt, DomainPartition & domain ) override; -#endif +#endif +protected: + //virtual void postInputInitialization() override; + + virtual void initializePostSubGroups() override; + + //virtual void initializePostInitialConditionsPreSubGroups() override; + + // virtual void postRestartInitialization() override final; + +private: + + /// name of the flow solver + string m_flowSolverName; + + /// flag indicating whether mass or molar formulation should be used + integer m_useMass; + + /// flag indicating whether total mass equation should be used + integer m_useTotalMassEquation; + + /// flag indicating whether thermal formulation is used + integer m_isThermal; + + /// flag indicating whether compositional formulation is used + bool m_isCompositional; + + /// flag to freeze the initial state during initialization in coupled problems + bool m_keepVariablesConstantDuringInitStep; + + /// number of phases + integer m_numFluidPhases; + + /// number of components + integer m_numFluidComponents; + + /// number of degrees of freedom per well element + integer m_numDofPerWellElement; + + /// number of degrees of freedom per reservoir element + integer m_numDofPerResElement; }; } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp index e565fae4508..36ad3e3607d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp @@ -36,7 +36,7 @@ using namespace fields; WellSolverBase::WellSolverBase( string const & name, Group * const parent ) - : PhysicsSolverBase( name, parent ), + : WellControls( name, parent ), m_numPhases( 0 ), m_numComponents( 0 ), m_numDofPerWellElement( 0 ), @@ -70,35 +70,35 @@ WellSolverBase::WellSolverBase( string const & name, Group * WellSolverBase::createChild( string const & childKey, string const & childName ) { + Group * baseChild = WellControls::createChild( childKey, childName ); + if( baseChild != nullptr ) + { + return baseChild; + } static std::set< string > const childTypes = { - keys::wellControls, + //keys::wellControls, PhysicsSolverBase::groupKeyStruct::linearSolverParametersString(), PhysicsSolverBase::groupKeyStruct::nonlinearSolverParametersString(), }; GEOS_ERROR_IF( childTypes.count( childKey ) == 0, CatalogInterface::unknownTypeError( childKey, getDataContext(), childTypes ), getDataContext() ); - if( childKey == keys::wellControls ) - { - return ®isterGroup< WellControls >( childName ); - } - else - { - PhysicsSolverBase::createChild( childKey, childName ); - return nullptr; - } + + PhysicsSolverBase::createChild( childKey, childName ); + return nullptr; + } void WellSolverBase::expandObjectCatalogs() { - createChild( keys::wellControls, keys::wellControls ); + //createChild( keys::wellControls, keys::wellControls ); } WellSolverBase::~WellSolverBase() = default; void WellSolverBase::postInputInitialization() { - PhysicsSolverBase::postInputInitialization(); + WellControls::postInputInitialization(); // 1. Set key dimensions of the problem m_numDofPerWellElement = m_isThermal ? m_numComponents + 2 : m_numComponents + 1; // 1 pressure connectionRate + temp if thermal diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp index 3e8d734c0e4..d1345044979 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp @@ -20,13 +20,13 @@ #ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLSOLVERBASE_HPP_ #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLSOLVERBASE_HPP_ -#include "physicsSolvers/PhysicsSolverBase.hpp" - +#include "physicsSolvers/fluidFlow/wells/WellControls.hpp" +#include "dataRepository/Group.hpp" namespace geos { class DomainPartition; -class WellControls; + class WellElementSubRegion; /** @@ -35,7 +35,7 @@ class WellElementSubRegion; * Base class for well solvers. * Provides some common features */ -class WellSolverBase : public PhysicsSolverBase +class WellSolverBase : public WellControls { public: @@ -60,7 +60,7 @@ class WellSolverBase : public PhysicsSolverBase WellSolverBase( WellSolverBase const & ) = delete; /// default move constructor - WellSolverBase( WellSolverBase && ) = default; + WellSolverBase( WellSolverBase && ) = delete; /// deleted assignment operator WellSolverBase & operator=( WellSolverBase const & ) = delete; @@ -128,7 +128,7 @@ class WellSolverBase : public PhysicsSolverBase */ virtual localIndex numFluidPhases() const = 0; - /** + /** * @brief getter for the well associated to this subRegion * @param subRegion the well subRegion whose controls are requested * @return a reference to the well diff --git a/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp b/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp index 425bccfa72c..17955899bf8 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp +++ b/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp @@ -147,7 +147,6 @@ initializePreSubGroups() CompositionalMultiphaseBase const * const flowSolver = this->flowSolver(); Base::wellSolver()->setFlowSolverName( flowSolver->getName() ); - bool const useMassFlow = flowSolver->getReference< integer >( CompositionalMultiphaseBase::viewKeyStruct::useMassFlagString() ); bool const useMassWell = Base::wellSolver()->template getReference< integer >( CompositionalMultiphaseWell::viewKeyStruct::useMassFlagString() ); GEOS_THROW_IF( useMassFlow != useMassWell, diff --git a/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.hpp b/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.hpp index b2b1f7a4800..b99975f2ba4 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.hpp +++ b/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.hpp @@ -23,7 +23,7 @@ #include "physicsSolvers/multiphysics/CoupledReservoirAndWellsBase.hpp" #include "physicsSolvers/fluidFlow/CompositionalMultiphaseBase.hpp" -#include "physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp" +#include "physicsSolvers/fluidFlow/wells/WellManager.hpp" namespace geos { @@ -31,12 +31,12 @@ namespace geos /// @tparam RESERVOIR_SOLVER compositional flow or compositional poromechanics solver template< typename RESERVOIR_SOLVER = CompositionalMultiphaseBase > class CompositionalMultiphaseReservoirAndWells : public CoupledReservoirAndWellsBase< RESERVOIR_SOLVER, - CompositionalMultiphaseWell > + WellManager > { public: using Base = CoupledReservoirAndWellsBase< RESERVOIR_SOLVER, - CompositionalMultiphaseWell >; + WellManager >; using Base::getLogLevel; using Base::m_solvers; using Base::m_linearSolverParameters; diff --git a/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellsBase.cpp b/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellsBase.cpp index fbb8e7fb935..d2fb522266a 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellsBase.cpp +++ b/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellsBase.cpp @@ -116,7 +116,7 @@ addCouplingNumNonzeros( PhysicsSolverBase const * const solver, } bool validateWellPerforations( PhysicsSolverBase const * const reservoirSolver, - WellSolverBase const * const wellSolver, + WellManager const * const wellSolver, DomainPartition const & domain ) { std::pair< string, string > badPerforation; diff --git a/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellsBase.hpp b/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellsBase.hpp index 32a67843aec..c7a1f3ea030 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellsBase.hpp +++ b/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellsBase.hpp @@ -29,7 +29,7 @@ #include "mesh/PerforationFields.hpp" #include "mesh/DomainPartition.hpp" #include "physicsSolvers/fluidFlow/wells/WellControls.hpp" -#include "physicsSolvers/fluidFlow/wells/WellSolverBase.hpp" +#include "physicsSolvers/fluidFlow/wells/WellManager.hpp" namespace geos { @@ -65,7 +65,7 @@ addCouplingNumNonzeros( PhysicsSolverBase const * const solver, * @param domain the physical domain object */ bool validateWellPerforations( PhysicsSolverBase const * const reservoirSolver, - WellSolverBase const * const wellSolver, + WellManager const * const wellSolver, DomainPartition const & domain ); } diff --git a/src/coreComponents/physicsSolvers/multiphysics/SinglePhaseReservoirAndWells.hpp b/src/coreComponents/physicsSolvers/multiphysics/SinglePhaseReservoirAndWells.hpp index 0adeee58026..98da0ab2737 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/SinglePhaseReservoirAndWells.hpp +++ b/src/coreComponents/physicsSolvers/multiphysics/SinglePhaseReservoirAndWells.hpp @@ -23,7 +23,7 @@ #include "physicsSolvers/multiphysics/CoupledReservoirAndWellsBase.hpp" #include "physicsSolvers/fluidFlow/SinglePhaseBase.hpp" -#include "physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp" +#include "physicsSolvers/fluidFlow/wells/WellManager.hpp" namespace geos { @@ -31,12 +31,12 @@ namespace geos /// @tparam RESERVOIR_SOLVER single-phase flow or single-phase poromechanics solver template< typename RESERVOIR_SOLVER = SinglePhaseBase > class SinglePhaseReservoirAndWells : public CoupledReservoirAndWellsBase< RESERVOIR_SOLVER, - SinglePhaseWell > + WellManager > { public: using Base = CoupledReservoirAndWellsBase< RESERVOIR_SOLVER, - SinglePhaseWell >; + WellManager >; using Base::m_solvers; using Base::m_linearSolverParameters; From 6f56f1e1615bff3a804222ffdae563f7e9cede9a Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Wed, 14 Jan 2026 09:28:34 -0800 Subject: [PATCH 51/71] cleanup comments --- .../wells/CompositionalMultiphaseWell.cpp | 14 +- .../wells/CompositionalMultiphaseWell.hpp | 158 +++++++------ .../fluidFlow/wells/SinglePhaseWell.cpp | 5 +- .../fluidFlow/wells/SinglePhaseWell.hpp | 72 +++--- .../fluidFlow/wells/WellControls.cpp | 19 +- .../fluidFlow/wells/WellControls.hpp | 65 +++--- .../fluidFlow/wells/WellSolverBase.cpp | 9 +- .../fluidFlow/wells/WellSolverBase.hpp | 199 +++++++++-------- .../CompositionalMultiphaseWellKernels.cpp | 209 ------------------ 9 files changed, 259 insertions(+), 491 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 3515711e05c..aa74a631b40 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -81,8 +81,7 @@ CompositionalMultiphaseWell::CompositionalMultiphaseWell( const string & name, m_maxRelativePresChange( 0.2 ), m_maxAbsolutePresChange( -1 ), // disabled by default m_minScalingFactor( 0.01 ), - m_allowCompDensChopping( 1 ), - m_targetPhaseIndex( -1 ) + m_allowCompDensChopping( 1 ) { this->registerWrapper( viewKeyStruct::useMassFlagString(), &m_useMass ). setApplyDefaultValue( 0 ). @@ -1839,7 +1838,6 @@ CompositionalMultiphaseWell::scalingForWellSystemSolution( ElementSubRegionBase minCompDensScalingFactor = std::min( minCompDensScalingFactor, subRegionData.localMinCompDensScalingFactor ); minTempScalingFactor = std::min( minTempScalingFactor, subRegionData.localMinTempScalingFactor ); - scalingFactor = MpiWrapper::min( scalingFactor ); maxDeltaPres = MpiWrapper::max( maxDeltaPres ); maxDeltaCompDens = MpiWrapper::max( maxDeltaCompDens ); @@ -1863,7 +1861,6 @@ CompositionalMultiphaseWell::scalingForWellSystemSolution( ElementSubRegionBase getName(), GEOS_FMT( "{:.{}f}", maxDeltaTemp, 3 ) ) ); } - GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, GEOS_FMT( " {}: Min well pressure scaling factor: {}", getName(), minPresScalingFactor ) ); @@ -1877,7 +1874,6 @@ CompositionalMultiphaseWell::scalingForWellSystemSolution( ElementSubRegionBase getName(), minTempScalingFactor ) ); } - return LvArray::math::max( scalingFactor, m_minScalingFactor ); } @@ -2181,7 +2177,7 @@ void CompositionalMultiphaseWell::computeWellPerforationRates( real64 const & ti } else { -// Zero completion flow rate + // Zero completion flow rate arrayView2d< real64 > const compPerfRate = perforationData->getField< fields::well::compPerforationRate >(); for( integer iperf=0; iperfsize(); iperf++ ) { @@ -2377,7 +2373,6 @@ CompositionalMultiphaseWell::applySystemSolution( DofManager const & dofManager, true ); } ); - } void CompositionalMultiphaseWell::chopNegativeDensities( WellElementSubRegion & subRegion ) @@ -2522,11 +2517,10 @@ void CompositionalMultiphaseWell::assembleWellConstraintTerms( real64 const & ti ProductionConstraint< LiquidRateConstraint > >( [&]( auto & constraint ) { + // Need to use name since there could be multiple constraints of the same type if( constraint.getName() == wellControls.getCurrentConstraint()->getName()) { // found limiting constraint - - // fluid data constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); integer isThermal = fluidSeparator.isThermal(); integer const numComp = fluidSeparator.numFluidComponents(); @@ -2557,8 +2551,6 @@ void CompositionalMultiphaseWell::assembleWellConstraintTerms( real64 const & ti if( constraint.getName() == wellControls.getCurrentConstraint()->getName()) { // found limiting constraint - - // fluid data constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); integer isThermal = fluidSeparator.isThermal(); integer const numComp = fluidSeparator.numFluidComponents(); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp index 6ad93ec3f44..e09e05e3f12 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp @@ -83,6 +83,9 @@ class CompositionalMultiphaseWell : public WellSolverBase */ string getCatalogName() const override { return catalogName(); } + /** + * @copydoc PhysicsSolverBase::registerDataOnMesh() + */ virtual void registerDataOnMesh( Group & meshBodies ) override; @@ -90,9 +93,19 @@ class CompositionalMultiphaseWell : public WellSolverBase * @defgroup Solver Interface Functions * * These functions provide the primary interface that is required for derived classes + * The "Well" versions apply to individual well subRegions, whereas the others apply to all wells */ /**@{*/ + /** + * @copydoc PhysicsSolverBase::calculateResidualNorm() + */ + virtual real64 + calculateResidualNorm( real64 const & time_n, + real64 const & dt, + DomainPartition const & domain, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs ) override; virtual real64 calculateWellResidualNorm( real64 const & time_n, @@ -101,34 +114,42 @@ class CompositionalMultiphaseWell : public WellSolverBase DofManager const & dofManager, arrayView1d< real64 const > const & localRhs ) override; + /** + * @copydoc PhysicsSolverBase::scalingForSystemSolution() + */ virtual real64 - calculateResidualNorm( real64 const & time_n, - real64 const & dt, - DomainPartition const & domain, - DofManager const & dofManager, - arrayView1d< real64 const > const & localRhs ) override; + scalingForSystemSolution( DomainPartition & domain, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution ) override; virtual real64 scalingForWellSystemSolution( ElementSubRegionBase & subRegion, DofManager const & dofManager, arrayView1d< real64 const > const & localSolution ) override; - virtual real64 - scalingForSystemSolution( DomainPartition & domain, - DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution ) override; - + /** + * @copydoc PhysicsSolverBase::checkSystemSolution() + */ + virtual bool + checkSystemSolution( DomainPartition & domain, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor ) override; virtual bool checkWellSystemSolution( ElementSubRegionBase & subRegion, DofManager const & dofManager, arrayView1d< real64 const > const & localSolution, real64 const scalingFactor ) override; - virtual bool - checkSystemSolution( DomainPartition & domain, - DofManager const & dofManager, + /** + * @copydoc PhysicsSolverBase::applySystemSolution() + */ + virtual void + applySystemSolution( DofManager const & dofManager, arrayView1d< real64 const > const & localSolution, - real64 const scalingFactor ) override; + real64 const scalingFactor, + real64 const dt, + DomainPartition & domain ) override; virtual void applyWellSystemSolution( DofManager const & dofManager, @@ -139,13 +160,6 @@ class CompositionalMultiphaseWell : public WellSolverBase MeshLevel & mesh, WellElementSubRegion & subRegion ) override; - virtual void - applySystemSolution( DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution, - real64 const scalingFactor, - real64 const dt, - DomainPartition & domain ) override; - virtual void resetStateToBeginningOfStep( DomainPartition & domain ) override; @@ -224,7 +238,6 @@ class CompositionalMultiphaseWell : public WellSolverBase ElementRegionManager const & elemManager, WellElementSubRegion & subRegion )override; - /** * @brief Recompute the perforation rates for all the wells * @param domain the domain containing the mesh and fields @@ -237,9 +250,9 @@ class CompositionalMultiphaseWell : public WellSolverBase * @param subRegion the well subregion containing all the primary and dependent fields */ virtual real64 updateWellState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) override; + /** - * @brief Recompute all dependent quantities from primary variables (including constitutive - * models) + * @brief Recompute all dependent quantities from primary variables (including constitutive models) * @param domain the domain containing the mesh and fields */ virtual void updateState( DomainPartition & domain ) override; @@ -256,21 +269,9 @@ class CompositionalMultiphaseWell : public WellSolverBase integer useTotalMassEquation() const { return m_useTotalMassEquation; } - virtual void assembleWellFluxTerms( real64 const & time, - real64 const & dt, - WellElementSubRegion const & subRegion, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) override; /** - * @brief assembles the flux terms for all connections between well elements - * @param time_n previous time value - * @param dt time step - * @param domain the physical domain object - * @param dofManager degree-of-freedom manager associated with the linear system - * @param matrix the system matrix - * @param rhs the system right-hand side vector + * @copydoc WellSolverBase::assembleFluxTerms() */ virtual void assembleFluxTerms( real64 const & time_n, @@ -280,19 +281,18 @@ class CompositionalMultiphaseWell : public WellSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs )override; - virtual void assembleWellAccumulationTerms( real64 const & time, - real64 const & dt, - WellElementSubRegion & subRegion, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) override; + /** + * @copydoc WellSolverBase::assembleFluxTerms() + */ + virtual void assembleWellFluxTerms( real64 const & time, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; /** - * @brief assembles the accumulation term for all the well elements - * @param domain the physical domain object - * @param dofManager degree-of-freedom manager associated with the linear system - * @param matrix the system matrix - * @param rhs the system right-hand side vector + * @copydoc WellSolverBase::assembleAccumulationTerms() */ virtual void assembleAccumulationTerms( real64 const & time_n, real64 const & dt, @@ -300,7 +300,19 @@ class CompositionalMultiphaseWell : public WellSolverBase DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) override; + /** + * @copydoc WellSolverBase::assembleWellAccumulationTerms() + */ + virtual void assembleWellAccumulationTerms( real64 const & time, + real64 const & dt, + WellElementSubRegion & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; + /** + * @copydoc WellSolverBase::assembleWellConstraintTerms() + */ virtual void assembleWellConstraintTerms( real64 const & time_n, real64 const & dt, WellElementSubRegion const & subRegion, @@ -308,22 +320,8 @@ class CompositionalMultiphaseWell : public WellSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) override; - - virtual void assembleWellPressureRelations( real64 const & time_n, - real64 const & dt, - WellElementSubRegion const & subRegion, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) override; - /** - * @brief assembles the pressure relations at all connections between well elements except at the well head - * @param time_n time at the beginning of the time step - * @param dt the time step size - * @param domain the physical domain object - * @param dofManager degree-of-freedom manager associated with the linear system - * @param matrix the system matrix - * @param rhs the system right-hand side vector + * @copydoc WellSolverBase::assemblePressureRelations() */ virtual void assemblePressureRelations( real64 const & time_n, real64 const & dt, @@ -331,6 +329,15 @@ class CompositionalMultiphaseWell : public WellSolverBase DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) override; + /** + * @copydoc WellSolverBase::assembleWellPressureRelations() + */ + virtual void assembleWellPressureRelations( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; /** * @brief Sets all the negative component densities (if any) to zero. @@ -431,6 +438,12 @@ class CompositionalMultiphaseWell : public WellSolverBase real64 const & dt, DomainPartition & domain ) override; + /** + * @brief Function to evaluate well constraints after applying the solution update + * @param time_n the time at the beginning of the time step + * @param subRegion the well subRegion + * @return true if all constraints are satisfied, false otherwise + */ virtual bool evaluateConstraints( real64 const & time_n, WellElementSubRegion & subRegion ) override; @@ -438,20 +451,6 @@ class CompositionalMultiphaseWell : public WellSolverBase virtual void setConstitutiveNames( ElementSubRegionBase & subRegion ) const override; - template< typename ... GROUPTYPES > - void selectLimitingConstraint( real64 const & time_n, integer const coupledIterationNumber, WellElementSubRegion & subRegion ); - - void solveConstraint( std::shared_ptr< WellConstraintBase > constraint, - real64 const & time_n, - real64 const & dt, - integer const cycleNumber, - integer const coupledIterationNumber, - DomainPartition & domain, - MeshLevel & mesh, - ElementRegionManager & elemManager, - WellElementSubRegion & subRegion, - DofManager const & dofManager ); - /// flag indicating whether mass or molar formulation should be used integer m_useMass; @@ -480,11 +479,6 @@ class CompositionalMultiphaseWell : public WellSolverBase /// flag indicating whether local (cell-wise) chopping of negative compositions is allowed integer m_allowCompDensChopping; - /// index of the target phase, used to impose the phase rate constraint - localIndex m_targetPhaseIndex; - - - }; } // namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index 7ddc8536125..2a6a688632b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -789,9 +789,8 @@ void SinglePhaseWell::assembleSystem( real64 const time, { WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) .getGroup< WellElementSubRegion >( region.getSubRegionName() ); - WellControls & wellControls = getWellControls( subRegion ); - if( !wellControls.getConstraintSwitch() ) - assembleWellConstraintTerms( time, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); + + assembleWellConstraintTerms( time, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); } ); } ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp index fb22dd9feb5..760c295704e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp @@ -92,18 +92,10 @@ class SinglePhaseWell : public WellSolverBase * @defgroup Solver Interface Functions * * These functions provide the primary interface that is required for derived classes + * The "Well" versions apply to individual well subRegions, whereas the others apply to all wells */ /**@{*/ - virtual real64 scalingForWellSystemSolution( ElementSubRegionBase & subRegion, - DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution ) override; - virtual real64 - calculateWellResidualNorm( real64 const & time_n, - real64 const & dt, - WellElementSubRegion const & subRegion, - DofManager const & dofManager, - arrayView1d< real64 const > const & localRhs ) override; virtual real64 calculateResidualNorm( real64 const & time_n, real64 const & dt, @@ -111,18 +103,41 @@ class SinglePhaseWell : public WellSolverBase DofManager const & dofManager, arrayView1d< real64 const > const & localRhs ) override; - virtual bool - checkWellSystemSolution( ElementSubRegionBase & subRegion, - DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution, - real64 const scalingFactor ) override; + virtual real64 + calculateWellResidualNorm( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs ) override; + + virtual real64 scalingForWellSystemSolution( ElementSubRegionBase & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution ) override; + /** + * @copydoc PhysicsSolverBase::checkSystemSolution() + */ virtual bool checkSystemSolution( DomainPartition & domain, DofManager const & dofManager, arrayView1d< real64 const > const & localSolution, real64 const scalingFactor ) override; + virtual bool + checkWellSystemSolution( ElementSubRegionBase & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor ) override; + /** + * @copydoc PhysicsSolverBase::applySystemSolution() + */ + virtual void + applySystemSolution( DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor, + real64 const dt, + DomainPartition & domain ) override; + virtual void applyWellSystemSolution( DofManager const & dofManager, arrayView1d< real64 const > const & localSolution, @@ -131,12 +146,6 @@ class SinglePhaseWell : public WellSolverBase DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion ) override; - virtual void - applySystemSolution( DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution, - real64 const scalingFactor, - real64 const dt, - DomainPartition & domain ) override; virtual void resetStateToBeginningOfStep( DomainPartition & domain ) override; @@ -279,17 +288,8 @@ class SinglePhaseWell : public WellSolverBase arrayView1d< real64 > const & localRhs ) override; /** - * @brief assembles the volume balance terms for all well elements - * @param domain the physical domain object - * @param dofManager degree-of-freedom manager associated with the linear system - * @param matrix the system matrix - * @param rhs the system right-hand side vector + * @copydoc WellSolverBase::assembleWellConstraintTerms() */ - void assembleVolumeBalanceTerms( DomainPartition const & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ); - virtual void assembleWellConstraintTerms( real64 const & time_n, real64 const & dt, WellElementSubRegion const & subRegion, @@ -322,6 +322,18 @@ class SinglePhaseWell : public WellSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) override; + /** + * @brief assembles the volume balance terms for all well elements + * @param domain the physical domain object + * @param dofManager degree-of-freedom manager associated with the linear system + * @param matrix the system matrix + * @param rhs the system right-hand side vector + */ + void assembleVolumeBalanceTerms( DomainPartition const & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ); + /** * @brief Initialize all the primary and secondary variables in all the wells * @param domain the domain containing the well manager to access individual wells diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index 382dcc5d109..8b169bce250 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -33,18 +33,16 @@ WellControls::WellControls( string const & name, Group * const parent ) : Group( name, parent ), m_type( Type::PRODUCER ), m_inputControl( Control::UNINITIALIZED ), - m_currentControl( Control::UNINITIALIZED ), // tjb remove + m_currentControl( Control::UNINITIALIZED ), m_useSurfaceConditions( 0 ), m_surfacePres( -1.0 ), m_surfaceTemp( -1.0 ), m_isCrossflowEnabled( 1 ), m_initialPressureCoefficient( 0.1 ), - m_rateSign( -1.0 ), - m_statusTable( nullptr ), - m_wellOpen( false ), - m_constraintSwitch( true ), m_currentConstraint( nullptr ), m_wellStatus( WellControls::Status::OPEN ), + m_wellOpen( false ), + m_statusTable( nullptr ), m_regionAveragePressure( -1 ) { setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); @@ -338,17 +336,6 @@ bool WellControls::getWellState() const return m_wellOpen; } -void WellControls::setConstraintSwitch( bool constraintSwitch ) -{ - m_constraintSwitch = constraintSwitch; -} - -bool WellControls::getConstraintSwitch() const -{ - return m_constraintSwitch; -} - - void WellControls::setNextDtFromTables( real64 const & currentTime, real64 & nextDt ) { if( isProducer() ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp index 625891c00ff..c7829d89d1c 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp @@ -254,7 +254,6 @@ class WellControls : public dataRepository::Group */ ///@{ - /** * @brief Get the control type for the well. * @return the Control enum enforced at the well @@ -273,7 +272,6 @@ class WellControls : public dataRepository::Group */ Control getInputControl() const { return m_inputControl; } - /** * @brief Getter for the reference gravity coefficient * @return the reference gravity coefficient @@ -285,7 +283,6 @@ class WellControls : public dataRepository::Group */ void setReferenceGravityCoef( real64 const & refGravCoef ) { m_refGravCoef = refGravCoef; } - /** * @brief Returns the target bottom hole pressure value. * @param[in] targetTime time at which to evaluate the constraint @@ -306,7 +303,6 @@ class WellControls : public dataRepository::Group */ arrayView1d< real64 const > getInjectionStream() const; - /** * @brief Const accessor for the phase constraint index * @return phase index associated with phase constraint @@ -362,14 +358,26 @@ class WellControls : public dataRepository::Group */ bool isWellOpen() const; + /** + * @brief Set the well state + * @param[in] open boolean + */ void setWellState( bool open ); + /** + * @brief Get the well state + * @return a boolean + */ bool getWellState() const; - - void setConstraintSwitch( bool constraintSwitch ); - bool getConstraintSwitch() const; - + /** + * @brief Set the current consrtaint + * @param[in] currentConstraint pointer to constraint + */ void setCurrentConstraint( WellConstraintBase * currentConstraint ) { m_currentConstraint = currentConstraint;} + /** + * @brief Get the current consrtaint + * @return pointer to constraint + */ WellConstraintBase * getCurrentConstraint() { return m_currentConstraint; } WellConstraintBase const * getCurrentConstraint() const { return m_currentConstraint; } @@ -411,7 +419,6 @@ class WellControls : public dataRepository::Group */ constitutive::SingleFluidBase & getSingleFluidSeparator() { return dynamicCast< constitutive::SingleFluidBase & >( *m_fluidSeparatorPtr ); } - /** * @brief Getter for the reservoir average pressure when m_useSurfaceConditions == 0 * @return the pressure @@ -524,7 +531,10 @@ class WellControls : public dataRepository::Group MinimumBHPConstraint * getMinBHPConstraint() const { return m_minBHPConstraint; }; MaximumBHPConstraint * getMaxBHPConstraint() { return m_maxBHPConstraint; }; MaximumBHPConstraint * getMaxBHPConstraint() const { return m_maxBHPConstraint; }; - // Lists of rate constraints + + /** + * @brief Getters for constraint lists + */ std::vector< WellConstraintBase * > getProdRateConstraints() { return m_productionRateConstraintList; }; std::vector< WellConstraintBase * > getProdRateConstraints() const { return m_productionRateConstraintList; }; std::vector< WellConstraintBase * > getInjRateConstraints() { return m_injectionRateConstraintList; } @@ -533,8 +543,6 @@ class WellControls : public dataRepository::Group virtual void postInputInitialization() override; - - private: /// Well type (as Type enum) @@ -567,10 +575,6 @@ class WellControls : public dataRepository::Group /// Surface temperature real64 m_surfaceTemp; - - /// Well status table name - string m_statusTableName; - /// Perforation status table name string m_perfStatusTableName; @@ -580,29 +584,13 @@ class WellControls : public dataRepository::Group /// Tuning coefficient for the initial well pressure real64 m_initialPressureCoefficient; - /// Rate sign. +1 for injector, -1 for producer - real64 m_rateSign; - - - /// Status table - TableFunction const * m_statusTable; - - bool m_wellOpen; - - - - /// List of constraints - //constraint_array m_ConstraintList; - // Bool to trigger old/new constraint switch logic - bool m_constraintSwitch; - - // Current constraint + // Current constrint WellConstraintBase * m_currentConstraint; + // Minimum and maximum BHP and WHP constraints MinimumBHPConstraint * m_minBHPConstraint; MaximumBHPConstraint * m_maxBHPConstraint; - // Lists of rate constraints std::vector< WellConstraintBase * > m_productionRateConstraintList; std::vector< WellConstraintBase * > m_injectionRateConstraintList; @@ -610,6 +598,15 @@ class WellControls : public dataRepository::Group /// Well status WellControls::Status m_wellStatus; + /// Well open flag + bool m_wellOpen; + + /// Well status table name + string m_statusTableName; + + /// Status table + TableFunction const * m_statusTable; + /// Region average pressure used in volume rate constraint calculations real64 m_regionAveragePressure; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp index e565fae4508..e69b8d08410 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp @@ -319,6 +319,8 @@ void WellSolverBase::selectWellConstraint( real64 const & time_n, WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) .getGroup< WellElementSubRegion >( region.getSubRegionName() ); WellControls & wellControls = getWellControls( subRegion ); + // Intiialize well if it is open + // Well state estimated from reservoir conditions if( wellControls.isWellOpen() ) { if( !wellControls.getWellState() ) @@ -333,11 +335,8 @@ void WellSolverBase::selectWellConstraint( real64 const & time_n, wellControls.setWellState( 0 ); } - if( wellControls.getWellState()) { - wellControls.setConstraintSwitch( false ); - evaluateConstraints( time_n, subRegion ); @@ -410,9 +409,7 @@ void WellSolverBase::assembleSystem( real64 const time, { WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) .getGroup< WellElementSubRegion >( region.getSubRegionName() ); - WellControls & wellControls = getWellControls( subRegion ); - if( !wellControls.getConstraintSwitch() ) - assembleWellConstraintTerms( time, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); + assembleWellConstraintTerms( time, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); } ); } ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp index 9de04730e26..31de7cf41d6 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp @@ -154,17 +154,49 @@ class WellSolverBase : public PhysicsSolverBase * @defgroup Solver Interface Functions * * These functions provide the primary interface that is required for derived classes + * The "Well" versions apply to individual well subRegions, whereas the others apply to all wells + */ /**@{*/ virtual void registerDataOnMesh( Group & meshBodies ) override; - void selectWellConstraint( real64 const & time_n, - real64 const & dt, - integer const coupledIterationNumber, - DomainPartition & domain ); + virtual real64 + calculateWellResidualNorm( real64 const & GEOS_UNUSED_PARAM( time_n ), + real64 const & GEOS_UNUSED_PARAM( dt ), + WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ), + arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localRhs ) ) = 0; + virtual real64 + scalingForWellSystemSolution( ElementSubRegionBase & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ), + arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localSolution ) ) = 0; + virtual bool + checkWellSystemSolution( ElementSubRegionBase & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ), + arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localSolution ), + real64 const GEOS_UNUSED_PARAM( scalingFactor ) ) = 0; + virtual void + applyWellSystemSolution( DofManager const & GEOS_UNUSED_PARAM( dofManager ), + arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localSolution ), + real64 const GEOS_UNUSED_PARAM( scalingFactor ), + real64 const GEOS_UNUSED_PARAM( dt ), + DomainPartition & GEOS_UNUSED_PARAM( domain ), + MeshLevel & GEOS_UNUSED_PARAM( mesh ), + WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ) ) = 0; + + /** + * @brief function to set the next time step size + * @param[in] currentTime the current time + * @param[in] currentDt the current time step size + * @param[in] domain the domain object + * @return the prescribed time step size + */ + virtual real64 setNextDt( real64 const & currentTime, + real64 const & currentDt, + DomainPartition & domain ) override; virtual void setupDofs( DomainPartition const & domain, DofManager & dofManager ) const override; @@ -183,9 +215,24 @@ class WellSolverBase : public PhysicsSolverBase CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) override {} + /** + * @brief Selects the active well constraint based on current conditions + * @param[in] currentTime the current time + * @param[in] currentDt the current time step size + * @param[in] coupledIterationNumber the current coupled iteration number + * @param[in] domain the domain object + * @return the prescribed time step size + */ + void selectWellConstraint( real64 const & time_n, + real64 const & dt, + integer const coupledIterationNumber, + DomainPartition & domain ); /**@}*/ + /** + * @copydoc PhysicsSolverBase::assembleSystem() + */ virtual void assembleSystem( real64 const time, real64 const dt, DomainPartition & domain, @@ -193,40 +240,31 @@ class WellSolverBase : public PhysicsSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) override; - virtual void assembleWellFluxTerms( real64 const & GEOS_UNUSED_PARAM( time ), - real64 const & GEOS_UNUSED_PARAM( dt ), - WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), - DofManager const & GEOS_UNUSED_PARAM( dofManager ), - CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), - arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) = 0; - - /** - * @brief assembles the flux terms for all connections between well elements + * @brief assembles the flux terms for individual well for all connections between well elements * @param time_n previous time value * @param dt time step - * @param domain the physical domain object + * @param subRegion the well subregion containing all the primary and dependent fields * @param dofManager degree-of-freedom manager associated with the linear system * @param matrix the system matrix * @param rhs the system right-hand side vector */ + virtual void assembleFluxTerms( real64 const & time_n, real64 const & dt, DomainPartition & domain, DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) = 0; + virtual void assembleWellFluxTerms( real64 const & GEOS_UNUSED_PARAM( time ), + real64 const & GEOS_UNUSED_PARAM( dt ), + WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ), + CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), + arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) = 0; - virtual void assembleWellAccumulationTerms( real64 const & time, - real64 const & dt, - WellElementSubRegion & subRegion, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) = 0; - - /** * @brief assembles the accumulation term for all the well elements * @param domain the physical domain object @@ -240,7 +278,30 @@ class WellSolverBase : public PhysicsSolverBase DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) = 0; - + /** + * @brief assembles the accumulation term for an individual well + * @param time_n time at the beginning of the time step + * @param dt the time step size + * @param subRegion the well subregion containing all the primary and dependent fields + * @param dofManager degree-of-freedom manager associated with the linear system + * @param matrix the system matrix + * @param rhs the system right-hand side vector + */ + virtual void assembleWellAccumulationTerms( real64 const & time, + real64 const & dt, + WellElementSubRegion & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) = 0; + /** + * @brief assembles the constraint terms for an individual well + * @param time_n time at the beginning of the time step + * @param dt the time step size + * @param subRegion the well subregion containing all the primary and dependent fields + * @param dofManager degree-of-freedom manager associated with the linear system + * @param matrix the system matrix + * @param rhs the system right-hand side vector + */ virtual void assembleWellConstraintTerms( real64 const & GEOS_UNUSED_PARAM( time ), real64 const & GEOS_UNUSED_PARAM( dt ), WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), @@ -248,12 +309,6 @@ class WellSolverBase : public PhysicsSolverBase CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) = 0; - virtual void assembleWellPressureRelations ( real64 const & GEOS_UNUSED_PARAM( time ), - real64 const & GEOS_UNUSED_PARAM( dt ), - WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), - DofManager const & GEOS_UNUSED_PARAM( dofManager ), - CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), - arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) = 0; /** * @brief assembles the pressure relations at all connections between well elements except at * the well head @@ -270,6 +325,21 @@ class WellSolverBase : public PhysicsSolverBase DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) = 0; + /** + * @brief assembles the pressure relations for individual well at all connections between well elements except at the well head + * @param time_n time at the beginning of the time step + * @param dt the time step size + * @param subRegion the well subregion containing all the primary and dependent fields + * @param dofManager degree-of-freedom manager associated with the linear system + * @param matrix the system matrix + * @param rhs the system right-hand side vector + */ + virtual void assembleWellPressureRelations ( real64 const & GEOS_UNUSED_PARAM( time ), + real64 const & GEOS_UNUSED_PARAM( dt ), + WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ), + CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), + arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) = 0; /** * @brief Recompute all dependent quantities from primary variables (including constitutive @@ -314,77 +384,6 @@ class WellSolverBase : public PhysicsSolverBase real64 const & dt, DomainPartition & domain ) = 0; - virtual real64 - calculateWellResidualNorm( real64 const & GEOS_UNUSED_PARAM( time_n ), - real64 const & GEOS_UNUSED_PARAM( dt ), - WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), - DofManager const & GEOS_UNUSED_PARAM( dofManager ), - arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localRhs ) ) = 0; - - virtual real64 - scalingForWellSystemSolution( ElementSubRegionBase & GEOS_UNUSED_PARAM( subRegion ), - DofManager const & GEOS_UNUSED_PARAM( dofManager ), - arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localSolution ) ) = 0; - - virtual bool - checkWellSystemSolution( ElementSubRegionBase & GEOS_UNUSED_PARAM( subRegion ), - DofManager const & GEOS_UNUSED_PARAM( dofManager ), - arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localSolution ), - real64 const GEOS_UNUSED_PARAM( scalingFactor ) ) = 0; - virtual void - applyWellSystemSolution( DofManager const & GEOS_UNUSED_PARAM( dofManager ), - arrayView1d< real64 const > const & GEOS_UNUSED_PARAM( localSolution ), - real64 const GEOS_UNUSED_PARAM( scalingFactor ), - real64 const GEOS_UNUSED_PARAM( dt ), - DomainPartition & GEOS_UNUSED_PARAM( domain ), - MeshLevel & GEOS_UNUSED_PARAM( mesh ), - WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ) ) = 0; - - /** - * @brief Function to perform line search - * @param time_n time at the beginning of the step - * @param dt the perscribed timestep - * @param cycleNumber the current cycle number - * @param domain the domain object - * @param dofManager degree-of-freedom manager associated with the linear system - * @param localMatrix the system matrix - * @param rhs the system right-hand side vector - * @param solution the solution vector - * @param scaleFactor the scaling factor to apply to the solution - * @param lastResidual (in) target value below which to reduce residual norm, (out) achieved - * residual norm - * @return return true if line search succeeded, false otherwise - * - * This function implements a nonlinear newton method for implicit problems. It requires that - * the - * other functions in the solver interface are implemented in the derived physics solver. The - * nonlinear loop includes a simple line search algorithm, and will cut the timestep if - * convergence is not achieved according to the parameters in linearSolverParameters member. - */ - bool - lineSearch1( real64 const & time_n, - real64 const & dt, - integer const cycleNumber, - DomainPartition & domain, - ElementRegionManager & elemManager, - WellElementSubRegion & subRegion, - MeshLevel & mesh, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - ParallelVector & rhs, - ParallelVector & solution, - real64 const scaleFactor, - real64 & lastResidual ); - /** - * @brief function to set the next time step size - * @param[in] currentTime the current time - * @param[in] currentDt the current time step size - * @param[in] domain the domain object - * @return the prescribed time step size - */ - virtual real64 setNextDt( real64 const & currentTime, - real64 const & currentDt, - DomainPartition & domain ) override; /** * @brief Utility function to keep the well variables during a time step (used in diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp index 344c66a68c5..a0c71194971 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp @@ -31,215 +31,6 @@ namespace compositionalMultiphaseWellKernels using namespace constitutive; -/******************************** ControlEquationHelper ********************************/ - -GEOS_HOST_DEVICE -inline -void -ControlEquationHelper:: - selectLimitingConstraint( bool const isProducer, - WellControls::Control const & inputControl, - WellControls::Control const & currentControl, - integer const phasePhaseIndex, - real64 const & targetBHP, - real64 const & targetPhaseRate, - real64 const & targetTotalRate, - real64 const & targetMassRate, - 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 - bool controlIsViable = false; - - // The limiting flow rates are treated as upper limits, while the pressure limits - // are treated as lower limits in production wells and upper limits in injectors. - // The well changes its mode of control whenever the existing control mode would - // violate one of these limits. - - // Currently, the available constraints are: - // - Producer: BHP, PHASEVOLRATE - // - Injector: BHP, TOTALVOLRATE, MASSRATE - - // TODO: support GRAT, WRAT, LIQUID for producers and check if any of the active constraint is violated - - // BHP control - if( currentControl == WellControls::Control::BHP ) - { - // the control is viable if the reference oil rate is below the max rate for producers - if( isProducer ) - { - 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 ) ); - } - } - else // rate control - { - // the control is viable if the reference pressure is below/above the max/min pressure - if( isProducer ) - { - // targetBHP specifies a min pressure here - controlIsViable = ( currentBHP >= targetBHP ); - } - else - { - // targetBHP specifies a max pressure here - controlIsViable = ( currentBHP <= targetBHP ); - } - } - - if( controlIsViable ) - { - newControl = currentControl; - } - else - { - if( isProducer ) - { - newControl = ( currentControl == WellControls::Control::BHP ) - ? WellControls::Control::PHASEVOLRATE - : WellControls::Control::BHP; - } - else - { - if( isZero( targetMassRate ) ) - { - newControl = ( currentControl == WellControls::Control::BHP ) - ? WellControls::Control::TOTALVOLRATE - : WellControls::Control::BHP; - } - else - { - newControl = ( currentControl == WellControls::Control::BHP ) - ? WellControls::Control::MASSRATE - : WellControls::Control::BHP; - } - } - } -} - -template< integer NC, integer IS_THERMAL > -GEOS_HOST_DEVICE -inline -void -ControlEquationHelper:: - compute( globalIndex const rankOffset, - WellControls::Control const currentControl, - integer const targetPhaseIndex, - real64 const & targetBHP, - real64 const & targetPhaseRate, - real64 const & targetTotalRate, - real64 const & targetMassRate, - real64 const & targetValue, - real64 const & currentBHP, - arrayView1d< real64 const > const & dCurrentBHP, - arrayView1d< real64 const > const & currentPhaseVolRate, - arrayView2d< real64 const > const & dCurrentPhaseVolRate, - - real64 const & currentTotalVolRate, - arrayView1d< real64 const > const & dCurrentTotalVolRate, - real64 const & massDensity, - globalIndex const dofNumber, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) -{ - GEOS_UNUSED_VAR( targetValue ); // tjb keeping this around if needed to compare with old constraint eqn jacgen - using COFFSET_WJ = compositionalMultiphaseWellKernels::ColOffset_WellJac< NC, IS_THERMAL >; - using Deriv = multifluid::DerivativeOffset; - - localIndex const eqnRowIndex = dofNumber + ROFFSET::CONTROL - rankOffset; - globalIndex dofColIndices[COFFSET_WJ::nDer]{}; - for( integer ic = 0; ic < COFFSET_WJ::nDer; ++ic ) - { - dofColIndices[ ic ] = dofNumber + ic; - } - - real64 controlEqn = 0; - real64 dControlEqn[NC+2+IS_THERMAL]{}; - - // Note: We assume in the computation of currentBHP that the reference elevation - // is in the top well element. This is enforced by a check in the solver. - // If we wanted to allow the reference elevation to be outside the top - // well element, it would make more sense to check the BHP constraint in - // the well element that contains the reference elevation. - - // BHP control - if( currentControl == WellControls::Control::BHP ) - { - // control equation is a difference between current BHP and target BHP - controlEqn = currentBHP - targetBHP; - dControlEqn[COFFSET_WJ::dP] = dCurrentBHP[Deriv::dP]; - for( integer ic = 0; ic < NC; ++ic ) - { - dControlEqn[COFFSET_WJ::dC+ic] = dCurrentBHP[Deriv::dC+ic]; - } - if constexpr ( IS_THERMAL ) - - dControlEqn[COFFSET_WJ::dT] = dCurrentBHP[Deriv::dT]; - - } - // Oil volumetric rate control - else if( currentControl == WellControls::Control::PHASEVOLRATE ) - { - controlEqn = currentPhaseVolRate[targetPhaseIndex] - targetPhaseRate; - dControlEqn[COFFSET_WJ::dP] = dCurrentPhaseVolRate[targetPhaseIndex][COFFSET_WJ::dP]; - dControlEqn[COFFSET_WJ::dQ] = dCurrentPhaseVolRate[targetPhaseIndex][COFFSET_WJ::dQ]; - for( integer ic = 0; ic < NC; ++ic ) - { - dControlEqn[COFFSET_WJ::dC+ic] = dCurrentPhaseVolRate[targetPhaseIndex][COFFSET_WJ::dC+ic]; - } - if constexpr ( IS_THERMAL ) - dControlEqn[COFFSET_WJ::dT] = dCurrentPhaseVolRate[targetPhaseIndex][COFFSET_WJ::dT]; - } - // Total volumetric rate control - else if( currentControl == WellControls::Control::TOTALVOLRATE ) - { - controlEqn = currentTotalVolRate - targetTotalRate; - dControlEqn[COFFSET_WJ::dP] = dCurrentTotalVolRate[COFFSET_WJ::dP]; - dControlEqn[COFFSET_WJ::dQ] = dCurrentTotalVolRate[COFFSET_WJ::dQ]; - for( integer ic = 0; ic < NC; ++ic ) - { - dControlEqn[COFFSET_WJ::dC+ic] = dCurrentTotalVolRate[COFFSET_WJ::dC+ic]; - } - if constexpr ( IS_THERMAL ) - dControlEqn[COFFSET_WJ::dT] = 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]; - } - if constexpr ( IS_THERMAL ) - dControlEqn[COFFSET_WJ::dT] = massDensity*dCurrentTotalVolRate[COFFSET_WJ::dT]; - } - else - { - GEOS_ERROR( "This constraint is not supported in CompositionalMultiphaseWell" ); - } - localRhs[eqnRowIndex] += controlEqn; - - localMatrix.addToRowBinarySearchUnsorted< serialAtomic >( eqnRowIndex, - dofColIndices, - dControlEqn, - COFFSET_WJ::nDer ); - - -} /******************************** PressureRelationKernel ********************************/ From 5f56e7c713e7cb645576dc44ca3684931a7ef172 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Wed, 21 Jan 2026 05:19:23 -0800 Subject: [PATCH 52/71] WellManager implements physcissolver api, compo/singlephasewell implement wellcontrolWell apis, it links --- .../physicsSolvers/fluidFlow/CMakeLists.txt | 5 +- .../wells/CompositionalMultiphaseWell.cpp | 1418 ++++++----------- .../wells/CompositionalMultiphaseWell.hpp | 269 ++-- .../fluidFlow/wells/SinglePhaseWell.cpp | 1265 +++++---------- .../fluidFlow/wells/SinglePhaseWell.hpp | 282 ++-- .../fluidFlow/wells/WellControls.cpp | 107 +- .../fluidFlow/wells/WellControls.hpp | 361 ++++- .../fluidFlow/wells/WellManager.cpp | 661 +++++++- .../fluidFlow/wells/WellManager.hpp | 165 +- .../fluidFlow/wells/WellSolverBase.cpp | 88 +- .../fluidFlow/wells/WellSolverBase.hpp | 86 +- .../SinglePhasePerforationFluxKernels.hpp | 4 +- ...mpositionalMultiphaseReservoirAndWells.cpp | 19 +- 13 files changed, 2387 insertions(+), 2343 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt index aaa73ca1d6a..bebc6d1aa58 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt +++ b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt @@ -137,9 +137,9 @@ set( fluidFlowSolvers_headers wells/WellMassRateConstraint.hpp wells/WellPhaseVolumeRateConstraint.hpp wells/WellLiquidRateConstraint.hpp - wells/WellSolverBase.hpp + wells/WellManager.hpp - wells/WellSolverBaseFields.hpp + wells/LogLevelsInfo.hpp wells/kernels/SinglePhaseWellKernels.hpp wells/kernels/CompositionalMultiphaseWellKernels.hpp @@ -184,7 +184,6 @@ set( fluidFlowSolvers_sources wells/WellMassRateConstraint.cpp wells/WellPhaseVolumeRateConstraint.cpp wells/WellLiquidRateConstraint.cpp - wells/WellSolverBase.cpp wells/WellManager.cpp proppantTransport/ProppantTransport.cpp proppantTransport/ProppantTransportKernels.cpp ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index a48f513ee08..eee6a0f6dad 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -74,7 +74,7 @@ using namespace fields; CompositionalMultiphaseWell::CompositionalMultiphaseWell( const string & name, Group * const parent ) : - WellSolverBase( name, parent ), + WellControls( name, parent ), m_useMass( false ), m_useTotalMassEquation( 1 ), m_maxCompFracChange( 1.0 ), @@ -132,7 +132,7 @@ CompositionalMultiphaseWell::CompositionalMultiphaseWell( const string & name, void CompositionalMultiphaseWell::postInputInitialization() { - WellSolverBase::postInputInitialization(); + WellControls::postInputInitialization(); GEOS_ERROR_IF_GT_MSG( m_maxCompFracChange, 1.0, getWrapperDataContext( viewKeyStruct::maxCompFracChangeString() ) << @@ -145,12 +145,15 @@ void CompositionalMultiphaseWell::postInputInitialization() getWrapperDataContext( viewKeyStruct::maxRelativeCompDensChangeString() ) << ": The maximum relative change in component density must be larger than 0.0" ); } - +void CompositionalMultiphaseWell::setConstitutiveNames( ElementSubRegionBase & subRegion ) const +{ + setConstitutiveName< MultiFluidBase >( subRegion, viewKeyStruct::fluidNamesString(), "multiphase fluid" ); +} void CompositionalMultiphaseWell::registerWellDataOnMesh( WellElementSubRegion & subRegion ) { - // WellSolverBase::registerDataOnMesh( meshBodies ); replaced by following 2 lines - setConstitutiveNamesCallSuper( subRegion ); - setConstitutiveNames( subRegion ); + // WellControls::registerDataOnMesh( meshBodies ); replaced by following 2 lines + setConstitutiveNames ( subRegion ); + DomainPartition const & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); ConstitutiveManager const & cm = domain.getConstitutiveManager(); if( m_referenceFluidModelName.empty() ) @@ -177,6 +180,17 @@ void CompositionalMultiphaseWell::registerWellDataOnMesh( WellElementSubRegion & // The resizing of the arrays needs to happen here, before the call to initializePreSubGroups, // to make sure that the dimensions are properly set before the timeHistoryOutput starts its initialization. + subRegion.registerField< well::pressure >( getName() ); + subRegion.registerField< well::pressure_n >( getName() ); + + subRegion.registerField< well::temperature >( getName() ); + if( isThermal() ) + { + subRegion.registerField< well::temperature_n >( getName() ); + } + + subRegion.registerField< well::gravityCoefficient >( getName() ); + subRegion.registerField< well::globalCompDensity >( getName() ). reference().resizeDimension< 1 >( m_numComponents ); @@ -210,6 +224,8 @@ void CompositionalMultiphaseWell::registerWellDataOnMesh( WellElementSubRegion & subRegion.registerField< well::globalCompDensityScalingFactor >( getName() ); PerforationData & perforationData = *subRegion.getPerforationData(); + + perforationData.registerField< well::gravityCoefficient >( getName() ); perforationData.registerField< well::compPerforationRate >( getName() ). reference().resizeDimension< 1 >( m_numComponents ); @@ -267,10 +283,6 @@ void CompositionalMultiphaseWell::registerWellDataOnMesh( WellElementSubRegion & } -void CompositionalMultiphaseWell::setConstitutiveNames( ElementSubRegionBase & subRegion ) const -{ - setConstitutiveName< MultiFluidBase >( subRegion, viewKeyStruct::fluidNamesString(), "multiphase fluid" ); -} namespace { @@ -344,28 +356,28 @@ void CompositionalMultiphaseWell::validateWellConstraints( real64 const & time_n WellElementSubRegion const & subRegion ) { GEOS_UNUSED_VAR( time_n ); - WellControls & wellControls = getWellControls( subRegion ); - if( !wellControls.useSurfaceConditions() ) + + if( !useSurfaceConditions() ) { - bool const useSeg =wellControls.referenceReservoirRegion().empty(); + bool const useSeg = getReferenceReservoirRegion().empty(); GEOS_WARNING_IF( useSeg, "WellControls " <( getFlowSolverName() ); string_array const & targetRegionsNames = flowSolver.getTargetRegionNames(); auto const pos = std::find( targetRegionsNames.begin(), targetRegionsNames.end(), regionName ); GEOS_ERROR_IF( pos == targetRegionsNames.end(), GEOS_FMT( "{}: Region {} is not a target of the reservoir solver and cannot be used for referenceReservoirRegion in WellControl {}.", - getDataContext(), regionName, wellControls.getName() ) ); + getDataContext(), regionName, getName() ) ); } @@ -374,7 +386,7 @@ void CompositionalMultiphaseWell::validateWellConstraints( real64 const & time_n MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); // tjb - wellControls.forSubGroups< InjectionConstraint< PhaseVolumeRateConstraint >, ProductionConstraint< PhaseVolumeRateConstraint > >( [&]( auto & constraint ) + forSubGroups< InjectionConstraint< PhaseVolumeRateConstraint >, ProductionConstraint< PhaseVolumeRateConstraint > >( [&]( auto & constraint ) { constraint.validatePhaseType( fluid ); } ); @@ -385,7 +397,7 @@ void CompositionalMultiphaseWell::validateWellConstraints( real64 const & time_n void CompositionalMultiphaseWell::initializePostSubGroups() { - WellSolverBase::initializePostSubGroups(); + WellControls::initializePostSubGroups(); //DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); @@ -395,55 +407,41 @@ void CompositionalMultiphaseWell::initializePostSubGroups() void CompositionalMultiphaseWell::initializePostInitialConditionsPreSubGroups() { - WellSolverBase::initializePostInitialConditionsPreSubGroups(); - createSeparator(); + WellControls::initializePostInitialConditionsPreSubGroups(); + } -void CompositionalMultiphaseWell::postRestartInitialization() +void CompositionalMultiphaseWell::initializeWellPostInitialConditionsPreSubGroups( WellElementSubRegion & subRegion ) { - DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - // loop over the wells - mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, - WellElementSubRegion & subRegion ) + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + + constitutive::MultiFluidBase & fluid = subRegion.getConstitutiveModel< constitutive::MultiFluidBase >( fluidName ); + fluid.setMassFlag( m_useMass ); + createSeparator( subRegion ); +} +void CompositionalMultiphaseWell::postRestartInitialization( ) +{ + + // setup fluid separator + constitutive::MultiFluidBase & fluidSeparator = getMultiFluidSeparator(); + fluidSeparator.allocateConstitutiveData( *this, 1 ); + fluidSeparator.resize( 1 ); - { - // setup fluid separator - WellControls & wellControls = getWellControls( subRegion ); - constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); - fluidSeparator.allocateConstitutiveData( wellControls, 1 ); - fluidSeparator.resize( 1 ); - } ); - } ); } -void CompositionalMultiphaseWell::createSeparator() +void CompositionalMultiphaseWell::createSeparator( WellElementSubRegion & subRegion ) { - DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - // loop over the wells - mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - MultiFluidBase & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); - fluid.setMassFlag( m_useMass ); - // setup fluid separator - WellControls & wellControls = getWellControls( subRegion ); - string const fluidSeparatorName = wellControls.getName() + "Separator"; - std::unique_ptr< constitutive::ConstitutiveBase > fluidSeparatorPtr = fluid.deliverClone( fluidSeparatorName, &wellControls ); - fluidSeparatorPtr->allocateConstitutiveData( wellControls, 1 ); - fluidSeparatorPtr->resize( 1 ); - wellControls.setFluidSeparator( std::move( fluidSeparatorPtr )); - } ); - } ); + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); + fluid.setMassFlag( m_useMass ); + // setup fluid separator + string const fluidSeparatorName = getName() + "Separator"; + std::unique_ptr< constitutive::ConstitutiveBase > fluidSeparatorPtr = fluid.deliverClone( fluidSeparatorName, this ); + fluidSeparatorPtr->allocateConstitutiveData( *this, 1 ); + fluidSeparatorPtr->resize( 1 ); + setFluidSeparator( std::move( fluidSeparatorPtr )); + } void CompositionalMultiphaseWell::updateGlobalComponentFraction( WellElementSubRegion & subRegion ) const { @@ -474,13 +472,12 @@ void CompositionalMultiphaseWell::updateBHPForConstraint( WellElementSubRegion & arrayView1d< real64 const > const wellElemGravCoef = subRegion.getField< well::gravityCoefficient >(); // control data - WellControls & wellControls = getWellControls( subRegion ); - string const wellControlsName = wellControls.getName(); - real64 const & refGravCoef = wellControls.getReferenceGravityCoef(); - real64 & currentBHP = - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() ); + string const wellControlsName = getName(); + real64 const & refGravCoef = getReferenceGravityCoef(); + real64 & currentBHP = + getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() ); // bring everything back to host, capture the scalars by reference forAll< serialPolicy >( 1, [ pres, totalMassDens, @@ -514,14 +511,12 @@ void CompositionalMultiphaseWell::updateVolRatesForConstraint( WellElementSubReg integer const numPhase = m_numPhases; localIndex const iwelemRef = subRegion.getTopWellElementIndex(); - WellControls & wellControls = getWellControls( subRegion ); - // subRegion data arrayView1d< real64 const > const & connRate = subRegion.getField< well::mixtureConnectionRate >(); // fluid data - constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); + constitutive::MultiFluidBase & fluidSeparator = getMultiFluidSeparator(); arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const & phaseFrac = fluidSeparator.phaseFraction(); arrayView2d< real64 const, constitutive::multifluid::USD_FLUID > const & totalDens = fluidSeparator.totalDensity(); @@ -529,19 +524,19 @@ void CompositionalMultiphaseWell::updateVolRatesForConstraint( WellElementSubReg // control data - string const wellControlsName = wellControls.getName(); + string const wellControlsName = getName(); arrayView1d< real64 > const & currentPhaseVolRate = - wellControls.getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ); + getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ); real64 & currentTotalVolRate = - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() ); + getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() ); real64 & currentMassRate = - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() ); + getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() ); real64 & massDensity = - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::massDensityString() ); + getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::massDensityString() ); // bring everything back to host, capture the scalars by reference forAll< serialPolicy >( 1, [&numPhase, @@ -602,35 +597,35 @@ void CompositionalMultiphaseWell::calculateReferenceElementRates( WellElementSub integer const numPhase = m_numPhases; localIndex const iwelemRef = subRegion.getTopWellElementIndex(); - WellControls & wellControls = getWellControls( subRegion ); + // subRegion data arrayView1d< real64 const > const & connRate = subRegion.getField< fields::well::mixtureConnectionRate >(); // fluid data - constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); + constitutive::MultiFluidBase & fluidSeparator = getMultiFluidSeparator(); arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const & phaseFrac = fluidSeparator.phaseFraction(); arrayView2d< real64 const, constitutive::multifluid::USD_FLUID > const & totalDens = fluidSeparator.totalDensity(); arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const & phaseDens = fluidSeparator.phaseDensity(); // control data - string const wellControlsName = wellControls.getName(); - bool const logSurfaceCondition = isLogLevelActive< logInfo::BoundaryConditions >( wellControls.getLogLevel()); + string const wellControlsName = getName(); + bool const logSurfaceCondition = isLogLevelActive< logInfo::BoundaryConditions >( getLogLevel()); string const massUnit = m_useMass ? "kg" : "mol"; - integer const useSurfaceConditions = wellControls.useSurfaceConditions(); + integer const useSurfCond = useSurfaceConditions(); arrayView1d< real64 > const & currentPhaseVolRate = - wellControls.getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ); + getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ); real64 & currentTotalVolRate = - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() ); + getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() ); real64 & currentMassRate = - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() ); + getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() ); real64 & massDensity = - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::massDensityString() ); + getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::massDensityString() ); constitutive::constitutiveUpdatePassThru( fluidSeparator, [&] ( auto & castedFluidSeparator ) { @@ -645,7 +640,7 @@ void CompositionalMultiphaseWell::calculateReferenceElementRates( WellElementSub phaseDens, phaseFrac, logSurfaceCondition, - &useSurfaceConditions, + &useSurfCond, ¤tTotalVolRate, currentPhaseVolRate, ¤tMassRate, @@ -671,7 +666,7 @@ void CompositionalMultiphaseWell::calculateReferenceElementRates( WellElementSub currentTotalVolRate = currentTotalRate * totalDensInv; - if( logSurfaceCondition && useSurfaceConditions ) + if( logSurfaceCondition && useSurfCond ) { GEOS_LOG_RANK( GEOS_FMT( "{}: total fluid density at surface conditions = {} {}/sm3, total rate = {} {}/s, total surface volumetric rate = {} sm3/s", wellControlsName, totalDens[iwelemRef][0], massUnit, connRate[iwelemRef], massUnit, currentTotalVolRate ) ); @@ -696,7 +691,7 @@ void CompositionalMultiphaseWell::calculateReferenceElementRates( WellElementSub // Step 3.2: divide the total mass/molar rate by the (phase density * phase fraction) to get the phase volumetric rate currentPhaseVolRate[ip] = currentTotalRate * phaseFracTimesPhaseDensInv; - if( logSurfaceCondition && useSurfaceConditions ) + if( logSurfaceCondition && useSurfCond ) { GEOS_LOG_RANK( GEOS_FMT( "{}: density of phase {} at surface conditions = {} {}/sm3, phase surface volumetric rate = {} sm3/s", wellControlsName, ip, phaseDens[iwelemRef][0][ip], massUnit, currentPhaseVolRate[ip] ) ); @@ -745,8 +740,6 @@ void CompositionalMultiphaseWell::updateSeparator( ElementRegionManager const & localIndex const iwelemRef = subRegion.getTopWellElementIndex(); - WellControls & wellControls = getWellControls( subRegion ); - // subRegion data arrayView1d< real64 const > const & pres = subRegion.getField< fields::well::pressure >(); arrayView1d< real64 const > const & temp = subRegion.getField< fields::well::temperature >(); @@ -754,43 +747,43 @@ void CompositionalMultiphaseWell::updateSeparator( ElementRegionManager const & // fluid data - constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); + constitutive::MultiFluidBase & fluidSeparator = getMultiFluidSeparator(); // control data - string const wellControlsName = wellControls.getName(); - bool const logSurfaceCondition = isLogLevelActive< logInfo::BoundaryConditions >( wellControls.getLogLevel()); + string const wellControlsName = getName(); + bool const logSurfaceCondition = isLogLevelActive< logInfo::BoundaryConditions >( getLogLevel()); string const massUnit = m_useMass ? "kg" : "mol"; - integer const useSurfaceConditions = wellControls.useSurfaceConditions(); + integer const useSurfaceCond = useSurfaceConditions(); real64 flashPressure; real64 flashTemperature; - if( useSurfaceConditions ) + if( useSurfaceCond ) { // use surface conditions - flashPressure = wellControls.getSurfacePressure(); - flashTemperature = wellControls.getSurfaceTemperature(); + flashPressure = getSurfacePressure(); + flashTemperature = getSurfaceTemperature(); } else { - if( !wellControls.referenceReservoirRegion().empty() ) + if( !getReferenceReservoirRegion().empty() ) { - ElementRegionBase const & region = elemManager.getRegion( wellControls.referenceReservoirRegion() ); + ElementRegionBase const & region = elemManager.getRegion( getReferenceReservoirRegion() ); GEOS_ERROR_IF ( !region.hasWrapper( CompositionalMultiphaseStatistics::regionStatisticsName()), GEOS_FMT( "{}: WellControl {} referenceReservoirRegion field requires CompositionalMultiphaseStatistics to be configured for region {} ", - getDataContext(), wellControls.getName(), wellControls.referenceReservoirRegion() ) ); + getDataContext(), getName(), getReferenceReservoirRegion() ) ); CompositionalMultiphaseStatistics::RegionStatistics const & stats = region.getReference< CompositionalMultiphaseStatistics::RegionStatistics >( CompositionalMultiphaseStatistics::regionStatisticsName() ); GEOS_ERROR_IF( stats.averagePressure <= 0.0, GEOS_FMT( "{}: No region average quantities computed. WellControl {} referenceReservoirRegion field requires CompositionalMultiphaseStatistics to be configured for region {} ", - getDataContext(), wellControls.getName(), wellControls.referenceReservoirRegion() )); - wellControls.setRegionAveragePressure( stats.averagePressure ); - wellControls.setRegionAverageTemperature( stats.averageTemperature ); + getDataContext(), getName(), getReferenceReservoirRegion() )); + setRegionAveragePressure( stats.averagePressure ); + setRegionAverageTemperature( stats.averageTemperature ); } // If flashPressure is not set by region the value is defaulted to -1 and indicates to use top segment conditions - flashPressure = wellControls.getRegionAveragePressure(); + flashPressure = getRegionAveragePressure(); if( flashPressure < 0.0 ) { // region name not set, use segment conditions @@ -800,7 +793,7 @@ void CompositionalMultiphaseWell::updateSeparator( ElementRegionManager const & else { // use reservoir region averages - flashTemperature = wellControls.getRegionAverageTemperature(); + flashTemperature = getRegionAverageTemperature(); } } @@ -811,7 +804,7 @@ void CompositionalMultiphaseWell::updateSeparator( ElementRegionManager const & // bring everything back to host, capture the scalars by reference forAll< serialPolicy >( 1, [fluidSeparatorWrapper, wellControlsName, - useSurfaceConditions, + useSurfaceCond, flashPressure, flashTemperature, logSurfaceCondition, @@ -822,7 +815,7 @@ void CompositionalMultiphaseWell::updateSeparator( ElementRegionManager const & { // - Surface conditions: using the surface pressure provided by the user // - Reservoir conditions: using the pressure in the top element - if( useSurfaceConditions ) + if( useSurfaceCond ) { // we need to compute the surface density //fluidWrapper.update( iwelemRef, 0, surfacePres, surfaceTemp, compFrac[iwelemRef] ); @@ -902,42 +895,11 @@ real64 CompositionalMultiphaseWell::updateWellState( ElementRegionManager const } -void CompositionalMultiphaseWell::updateState( DomainPartition & domain ) -{ - GEOS_MARK_FUNCTION; - //tjb - real64 maxPhaseVolFrac = 0.0; - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - ElementRegionManager & elemManager = mesh.getElemManager(); - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - WellControls & wellControls = getWellControls( subRegion ); - if( wellControls.getWellState()) - { - - real64 const maxRegionPhaseVolFrac = updateWellState( elemManager, subRegion ); - - maxPhaseVolFrac = LvArray::math::max( maxRegionPhaseVolFrac, maxPhaseVolFrac ); - } - } ); - } ); - maxPhaseVolFrac = MpiWrapper::max( maxPhaseVolFrac ); - - GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, - GEOS_FMT( " {}: Max well phase volume fraction change = {}", - getName(), fmt::format( "{:.{}f}", maxPhaseVolFrac, 4 ) ) ); - -} - real64 CompositionalMultiphaseWell::updateSubRegionState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) { real64 maxPhaseVolChange=0.0; - WellControls & wellControls = getWellControls( subRegion ); - if( wellControls.getWellState()) + + if( getWellState()) { // update properties @@ -962,13 +924,13 @@ real64 CompositionalMultiphaseWell::updateSubRegionState( ElementRegionManager c // Broad case the updated well state to other ranks real64 & currentBHP = - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() ); + getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() ); array1d< real64 > currentPhaseVolRate = - wellControls.getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ); + getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ); real64 & currentTotalVolRate = - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() ); + getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() ); real64 & currentMassRate = - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() ); + getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() ); integer topRank = subRegion.getTopRank(); MpiWrapper::broadcast( currentBHP, topRank ); MpiWrapper::bcast( currentPhaseVolRate.data(), LvArray::integerConversion< int >( currentPhaseVolRate.size() ), topRank ); @@ -976,7 +938,7 @@ real64 CompositionalMultiphaseWell::updateSubRegionState( ElementRegionManager c MpiWrapper::broadcast( currentMassRate, topRank ); if( !subRegion.isLocallyOwned() ) { - wellControls.getReference< array1d< real64 > >( + getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) =currentPhaseVolRate; @@ -994,38 +956,36 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh integer const numComp = m_numComponents; integer const numPhase = m_numPhases; - m_nextDt = -1; + // TODO: change the way we access the flowSolver here - CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); ElementRegionManager const & elemManager = mesh.getElemManager(); compositionalMultiphaseWellKernels::PresTempCompFracInitializationKernel::CompFlowAccessors - resCompFlowAccessors( elemManager, flowSolver.getName() ); + resCompFlowAccessors( elemManager, getFlowSolverName() ); compositionalMultiphaseWellKernels::PresTempCompFracInitializationKernel::MultiFluidAccessors - resMultiFluidAccessors( elemManager, flowSolver.getName() ); + resMultiFluidAccessors( elemManager, getFlowSolverName() ); - WellControls & wellControls = getWellControls( subRegion ); PerforationData const & perforationData = *subRegion.getPerforationData(); arrayView2d< real64 const > const compPerfRate = perforationData.getField< fields::well::compPerforationRate >(); bool const hasNonZeroRate = MpiWrapper::max< integer >( hasNonZero( compPerfRate )); - if( time_n <= 0.0 || ( wellControls.isWellOpen( ) && !hasNonZeroRate ) ) + if( time_n <= 0.0 || ( isWellOpen( ) && !hasNonZeroRate ) ) { - wellControls.setWellState( true ); - if( wellControls.getCurrentConstraint() == nullptr ) + setWellState( true ); + if( getCurrentConstraint() == nullptr ) { // tjb needed for backward compatibility. and these 2 lists must be consistent - ConstraintTypeId inputControl = ConstraintTypeId( wellControls.getInputControl()); - if( wellControls.isProducer() ) + ConstraintTypeId inputControl = ConstraintTypeId( getInputControl()); + if( isProducer() ) { - wellControls.forSubGroups< MinimumBHPConstraint, ProductionConstraint< VolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, - ProductionConstraint< PhaseVolumeRateConstraint > >( [&]( auto & constraint ) + forSubGroups< MinimumBHPConstraint, ProductionConstraint< VolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, + ProductionConstraint< PhaseVolumeRateConstraint > >( [&]( auto & constraint ) { if( constraint.getControl() == inputControl ) { - wellControls.setCurrentConstraint( &constraint ); - wellControls.setControl( static_cast< WellControls::Control >(inputControl) ); // tjb old + setCurrentConstraint( &constraint ); + setControl( static_cast< WellControls::Control >(inputControl) ); // tjb old } } ); @@ -1033,13 +993,13 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh else { - wellControls.forSubGroups< MaximumBHPConstraint, InjectionConstraint< VolumeRateConstraint >, InjectionConstraint< MassRateConstraint >, - InjectionConstraint< PhaseVolumeRateConstraint > >( [&]( auto & constraint ) + forSubGroups< MaximumBHPConstraint, InjectionConstraint< VolumeRateConstraint >, InjectionConstraint< MassRateConstraint >, + InjectionConstraint< PhaseVolumeRateConstraint > >( [&]( auto & constraint ) { if( constraint.getControl() == inputControl ) { - wellControls.setCurrentConstraint( &constraint ); - wellControls.setControl( static_cast< WellControls::Control >(inputControl) ); // tjb old + setCurrentConstraint( &constraint ); + setControl( static_cast< WellControls::Control >(inputControl) ); // tjb old } } ); } @@ -1071,7 +1031,7 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh subRegion.size(), numComp, numPhase, - wellControls, + *this, 0.0, // initialization done at t = 0 resCompFlowAccessors.get( flow::pressure{} ), resCompFlowAccessors.get( flow::temperature{} ), @@ -1124,7 +1084,7 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh compositionalMultiphaseWellKernels:: RateInitializationKernel:: launch( subRegion.size(), - wellControls, + *this, time_n, // initialization done at time_n wellElemPhaseDens, wellElemTotalDens, @@ -1132,51 +1092,51 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh updateVolRatesForConstraint( subRegion ); // Since this is a well manager class the rates need to be pushed into the WellControls class, which represnets the well - WellConstraintBase * constraint = wellControls.getCurrentConstraint(); - constraint->setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); - constraint->setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( + WellConstraintBase * constraint = getCurrentConstraint(); + constraint->setBHP ( getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); + constraint->setPhaseVolumeRates ( getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); - constraint->setTotalVolumeRate ( wellControls.getReference< real64 >( + constraint->setTotalVolumeRate ( getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); - constraint->setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); + constraint->setMassRate( getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); // 7) Copy well / fluid dofs to "prop"_n variables saveState( subRegion ); } else if( !hasNonZeroRate ) { - wellControls.setWellState( false ); + setWellState( false ); GEOS_LOG_RANK_0( "tjb shut wells "<< subRegion.getName()); } else { - wellControls.setWellState( true ); + setWellState( true ); // setup if restart - if( wellControls.getCurrentConstraint() == nullptr ) + if( getCurrentConstraint() == nullptr ) { updateSubRegionState( elemManager, subRegion ); - if( wellControls.isProducer() ) + if( isProducer() ) { - wellControls.forSubGroups< MinimumBHPConstraint, ProductionConstraint< VolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, - ProductionConstraint< PhaseVolumeRateConstraint > >( [&]( - auto - & constraint ) + forSubGroups< MinimumBHPConstraint, ProductionConstraint< VolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, + ProductionConstraint< PhaseVolumeRateConstraint > >( [&]( + auto + & constraint ) { - if( ConstraintTypeId( wellControls.getControl()) == constraint.getControl() ) + if( ConstraintTypeId( getControl()) == constraint.getControl() ) { - wellControls.setCurrentConstraint( &constraint ); + setCurrentConstraint( &constraint ); } } ); } else { - wellControls.forSubGroups< MaximumBHPConstraint, InjectionConstraint< VolumeRateConstraint >, InjectionConstraint< MassRateConstraint >, InjectionConstraint< PhaseVolumeRateConstraint > >( [&]( - auto - & - constraint ) + forSubGroups< MaximumBHPConstraint, InjectionConstraint< VolumeRateConstraint >, InjectionConstraint< MassRateConstraint >, InjectionConstraint< PhaseVolumeRateConstraint > >( [&]( + auto + & + constraint ) { - if( ConstraintTypeId( wellControls.getControl()) == constraint.getControl() ) + if( ConstraintTypeId( getControl()) == constraint.getControl() ) { - wellControls.setCurrentConstraint( &constraint ); + setCurrentConstraint( &constraint ); } } ); } @@ -1186,35 +1146,6 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh } -void CompositionalMultiphaseWell::initializeWells( DomainPartition & domain, real64 const & time_n ) -{ - GEOS_MARK_FUNCTION; - m_nextDt = -1; - // TODO: change the way we access the flowSolver here - CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); - - // loop over the wells - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - - ElementRegionManager & elemManager = mesh.getElemManager(); - compositionalMultiphaseWellKernels::PresTempCompFracInitializationKernel::CompFlowAccessors - resCompFlowAccessors( mesh.getElemManager(), flowSolver.getName() ); - compositionalMultiphaseWellKernels::PresTempCompFracInitializationKernel::MultiFluidAccessors - resMultiFluidAccessors( mesh.getElemManager(), flowSolver.getName() ); - - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - - initializeWell( domain, mesh, subRegion, time_n ); - } ); - - } ); -} void CompositionalMultiphaseWell::assembleWellFluxTerms( real64 const & time, real64 const & dt, @@ -1232,8 +1163,8 @@ void CompositionalMultiphaseWell::assembleWellFluxTerms( real64 const & time, string const wellDofKey = dofManager.getKey( wellElementDofName()); - WellControls const & well_controls = getWellControls( subRegion ); - if( well_controls.isWellOpen( ) && !m_keepVariablesConstantDuringInitStep ) + + if( isWellOpen( ) && !m_keepVariablesConstantDuringInitStep ) { string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString()); MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); @@ -1248,7 +1179,7 @@ void CompositionalMultiphaseWell::assembleWellFluxTerms( real64 const & time, dofManager.rankOffset(), kernelFlags, wellDofKey, - well_controls, + *this, subRegion, fluid, localMatrix, @@ -1263,7 +1194,7 @@ void CompositionalMultiphaseWell::assembleWellFluxTerms( real64 const & time, dofManager.rankOffset(), kernelFlags, wellDofKey, - well_controls, + *this, subRegion, localMatrix, localRhs ); @@ -1273,68 +1204,6 @@ void CompositionalMultiphaseWell::assembleWellFluxTerms( real64 const & time, } -void CompositionalMultiphaseWell::assembleFluxTerms( real64 const & time, - real64 const & dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) -{ - GEOS_MARK_FUNCTION; - GEOS_UNUSED_VAR( time ); - - 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, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - - assembleWellFluxTerms( time, dt, subRegion, dofManager, localMatrix, localRhs ); - - } ); - } ); - -} - -void CompositionalMultiphaseWell::assembleAccumulationTerms( real64 const & time, - real64 const & dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) -{ - 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, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - - assembleWellAccumulationTerms( time, dt, subRegion, dofManager, localMatrix, localRhs ); - } ); - } ); - - -} void CompositionalMultiphaseWell::assembleWellAccumulationTerms( real64 const & time, real64 const & dt, @@ -1357,8 +1226,8 @@ void CompositionalMultiphaseWell::assembleWellAccumulationTerms( real64 const & MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); integer const numPhases = fluid.numFluidPhases(); integer const numComponents = fluid.numFluidComponents(); - WellControls & wellControls = getWellControls( subRegion ); - if( wellControls.getWellStatus() == WellControls::Status::OPEN && !m_keepVariablesConstantDuringInitStep ) + + if( getWellStatus() == WellControls::Status::OPEN && !m_keepVariablesConstantDuringInitStep ) { if( isThermal() ) { @@ -1367,7 +1236,7 @@ void CompositionalMultiphaseWell::assembleWellAccumulationTerms( real64 const & ElementBasedAssemblyKernelFactory:: createAndLaunch< parallelDevicePolicy<> >( numComponents, numPhases, - wellControls.isProducer(), + isProducer(), dofManager.rankOffset(), kernelFlags, wellDofKey, @@ -1382,7 +1251,7 @@ void CompositionalMultiphaseWell::assembleWellAccumulationTerms( real64 const & ElementBasedAssemblyKernelFactory:: createAndLaunch< parallelDevicePolicy<> >( numComponents, numPhases, - wellControls.isProducer(), + isProducer(), dofManager.rankOffset(), kernelFlags, wellDofKey, @@ -1454,22 +1323,22 @@ void CompositionalMultiphaseWell::assembleWellAccumulationTerms( real64 const & } } ); // zero out current state constraint quantities - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )=0.0; - wellControls.getReference< array1d< real64 > >( + getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )=0.0; + getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ).zero(); - wellControls.getReference< real64 >( + getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )=0.0; - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )=0.0; + getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )=0.0; } } - -real64 -CompositionalMultiphaseWell::calculateWellResidualNorm( real64 const & time_n, - real64 const & dt, - WellElementSubRegion const & subRegion, - DofManager const & dofManager, - arrayView1d< real64 const > const & localRhs ) +array1d< real64 > +CompositionalMultiphaseWell::calculateLocalWellResidualNorm( real64 const & time_n, + real64 const & dt, + NonlinearSolverParameters const & nonlinearSolverParameters, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs ) { GEOS_MARK_FUNCTION; integer numNorm = 1; // mass balance @@ -1492,9 +1361,7 @@ CompositionalMultiphaseWell::calculateWellResidualNorm( real64 const & time_n, string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); - WellControls const & wellControls = getWellControls( subRegion ); - - if( wellControls.isWellOpen( ) ) + if( isWellOpen( ) ) { // step 1: compute the norm in the subRegion if( isThermal() ) @@ -1508,10 +1375,10 @@ CompositionalMultiphaseWell::calculateWellResidualNorm( real64 const & time_n, localRhs, subRegion, fluid, - wellControls, + *this, time_n, dt, - m_nonlinearSolverParameters.m_minNormalizer, + nonlinearSolverParameters.m_minNormalizer, subRegionResidualNorm ); // step 2: reduction across meshBodies/regions/subRegions @@ -1529,16 +1396,16 @@ CompositionalMultiphaseWell::calculateWellResidualNorm( real64 const & time_n, real64 subRegionResidualNorm[1]{}; compositionalMultiphaseWellKernels::ResidualNormKernelFactory:: createAndLaunch< parallelDevicePolicy<> >( m_numComponents, - numDofPerWellElement(), + m_numDofPerWellElement, rankOffset, wellDofKey, localRhs, subRegion, fluid, - wellControls, + *this, time_n, dt, - m_nonlinearSolverParameters.m_minNormalizer, + nonlinearSolverParameters.m_minNormalizer, subRegionResidualNorm ); @@ -1559,39 +1426,19 @@ CompositionalMultiphaseWell::calculateWellResidualNorm( real64 const & time_n, } } - // step 3: second reduction across MPI ranks - real64 resNorm=localResidualNorm[0]; - if( isThermal() ) - { - real64 globalResidualNorm[2]{}; - globalResidualNorm[0] = MpiWrapper::max( localResidualNorm[0] ); - globalResidualNorm[1] = MpiWrapper::max( localResidualNorm[1] ); - resNorm=sqrt( globalResidualNorm[0] * globalResidualNorm[0] + globalResidualNorm[1] * globalResidualNorm[1] ); - - GEOS_LOG_LEVEL_RANK_0( logInfo::ResidualNorm, GEOS_FMT( " ( R{} ) = ( {:4.2e} ) ( Renergy ) = ( {:4.2e} )", - coupledSolverAttributePrefix(), globalResidualNorm[0], globalResidualNorm[1] )); - - } - else - { - resNorm= MpiWrapper::max( resNorm ); + return localResidualNorm; - GEOS_LOG_LEVEL_RANK_0( logInfo::ResidualNorm, GEOS_FMT( " ( R{} ) = ( {:4.2e} )", - coupledSolverAttributePrefix(), resNorm )); - } - return resNorm; } - real64 -CompositionalMultiphaseWell::calculateResidualNorm( real64 const & time_n, - real64 const & dt, - DomainPartition const & domain, - DofManager const & dofManager, - arrayView1d< real64 const > const & localRhs ) +CompositionalMultiphaseWell::calculateWellResidualNorm( real64 const & time_n, + real64 const & dt, + NonlinearSolverParameters const & nonlinearSolverParameters, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs ) { GEOS_MARK_FUNCTION; - integer numNorm = 1; // mass balance array1d< real64 > localResidualNorm; array1d< real64 > localResidualNormalizer; @@ -1607,93 +1454,29 @@ CompositionalMultiphaseWell::calculateResidualNorm( real64 const & time_n, globalIndex const rankOffset = dofManager.rankOffset(); string const wellDofKey = dofManager.getKey( wellElementDofName() ); - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel const & mesh, - string_array const & regionNames ) - { - - - ElementRegionManager const & elemManager = mesh.getElemManager(); - - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion const & subRegion ) - { - - - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); - WellControls const & wellControls = getWellControls( subRegion ); - // step 1: compute the norm in the subRegion - if( true ) // tjb wellControls.isWellOpen( ) ) - { - if( isThermal() ) - { - real64 subRegionResidualNorm[2]{}; - - thermalCompositionalMultiphaseWellKernels::ResidualNormKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( m_numComponents, - rankOffset, - wellDofKey, - localRhs, - subRegion, - fluid, - wellControls, - time_n, - dt, - m_nonlinearSolverParameters.m_minNormalizer, - subRegionResidualNorm ); - // step 2: reduction across meshBodies/regions/subRegions - - for( integer i=0; i localResidualNorm[i] ) - { - localResidualNorm[i] = subRegionResidualNorm[i]; - } - } + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); - } - else - { - real64 subRegionResidualNorm[1]{}; - compositionalMultiphaseWellKernels::ResidualNormKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( m_numComponents, - numDofPerWellElement(), - rankOffset, - wellDofKey, - localRhs, - subRegion, - fluid, - wellControls, - time_n, - dt, - m_nonlinearSolverParameters.m_minNormalizer, - subRegionResidualNorm ); - - - - // step 2: reduction across meshBodies/regions/subRegions - - if( subRegionResidualNorm[0] > localResidualNorm[0] ) - { - localResidualNorm[0] = subRegionResidualNorm[0]; - } - } - } - else - { - for( integer i=0; i const & localSolution ) + +void +CompositionalMultiphaseWell::scalingForLocalSystemSolution( WellElementSubRegion & subRegion, + DofManager const & dofManager, + real64 & maxDeltaPres, + real64 & maxDeltaCompDens, + real64 & maxDeltaTemp, + real64 & minPresScalingFactor, + real64 & minCompDensScalingFactor, + real64 & minTempScalingFactor, + arrayView1d< real64 const > const & localSolution ) { GEOS_MARK_FUNCTION; string const wellDofKey = dofManager.getKey( wellElementDofName() ); real64 scalingFactor = 1.0; - real64 maxDeltaPres = 0.0, maxDeltaCompDens = 0.0, maxDeltaTemp = 0.0; - real64 minPresScalingFactor = 1.0, minCompDensScalingFactor = 1.0, minTempScalingFactor = 1.0; + maxDeltaPres = 0.0; + maxDeltaCompDens = 0.0; + maxDeltaTemp = 0.0; + minPresScalingFactor = 1.0; + minCompDensScalingFactor = 1.0; + minTempScalingFactor = 1.0; arrayView1d< real64 const > const pressure = subRegion.getField< fields::well::pressure >(); arrayView1d< real64 const > const temperature = subRegion.getField< fields::well::temperature >(); @@ -1823,14 +1614,13 @@ CompositionalMultiphaseWell::scalingForWellSystemSolution( ElementSubRegionBase getName(), minTempScalingFactor ) ); } - return LvArray::math::max( scalingFactor, m_minScalingFactor ); -} +} real64 -CompositionalMultiphaseWell::scalingForSystemSolution( DomainPartition & domain, - DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution ) +CompositionalMultiphaseWell::scalingForWellSystemSolution( WellElementSubRegion & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution ) { GEOS_MARK_FUNCTION; @@ -1840,76 +1630,15 @@ CompositionalMultiphaseWell::scalingForSystemSolution( DomainPartition & domain, real64 maxDeltaPres = 0.0, maxDeltaCompDens = 0.0, maxDeltaTemp = 0.0; real64 minPresScalingFactor = 1.0, minCompDensScalingFactor = 1.0, minTempScalingFactor = 1.0; - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - arrayView1d< real64 const > const pressure = subRegion.getField< well::pressure >(); - arrayView1d< real64 const > const temperature = subRegion.getField< well::temperature >(); - arrayView2d< real64 const, compflow::USD_COMP > const compDens = subRegion.getField< well::globalCompDensity >(); - arrayView1d< real64 > pressureScalingFactor = subRegion.getField< well::pressureScalingFactor >(); - arrayView1d< real64 > temperatureScalingFactor = subRegion.getField< well::temperatureScalingFactor >(); - arrayView1d< real64 > compDensScalingFactor = subRegion.getField< well::globalCompDensityScalingFactor >(); - const integer temperatureOffset = m_numComponents+2; - auto const subRegionData = - m_isThermal - ? thermalCompositionalMultiphaseBaseKernels:: - SolutionScalingKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( m_maxRelativePresChange, - m_maxAbsolutePresChange, - m_maxRelativeTempChange, - m_maxCompFracChange, - m_maxRelativeCompDensChange, - pressure, - temperature, - compDens, - pressureScalingFactor, - compDensScalingFactor, - temperatureScalingFactor, - dofManager.rankOffset(), - m_numComponents, - wellDofKey, - subRegion, - localSolution, - temperatureOffset ) - : isothermalCompositionalMultiphaseBaseKernels:: - SolutionScalingKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( m_maxRelativePresChange, - m_maxAbsolutePresChange, - m_maxCompFracChange, - m_maxRelativeCompDensChange, - pressure, - compDens, - pressureScalingFactor, - compDensScalingFactor, - dofManager.rankOffset(), - m_numComponents, - wellDofKey, - subRegion, - localSolution ); - - - scalingFactor = std::min( subRegionData.localMinVal, scalingFactor ); - - maxDeltaPres = std::max( maxDeltaPres, subRegionData.localMaxDeltaPres ); - maxDeltaCompDens = std::max( maxDeltaCompDens, subRegionData.localMaxDeltaCompDens ); - maxDeltaTemp = std::max( maxDeltaTemp, subRegionData.localMaxDeltaTemp ); - minPresScalingFactor = std::min( minPresScalingFactor, subRegionData.localMinPresScalingFactor ); - minCompDensScalingFactor = std::min( minCompDensScalingFactor, subRegionData.localMinCompDensScalingFactor ); - minTempScalingFactor = std::min( minTempScalingFactor, subRegionData.localMinTempScalingFactor ); - } ); - } ); - - scalingFactor = MpiWrapper::min( scalingFactor ); - maxDeltaPres = MpiWrapper::max( maxDeltaPres ); - maxDeltaCompDens = MpiWrapper::max( maxDeltaCompDens ); - minPresScalingFactor = MpiWrapper::min( minPresScalingFactor ); - minCompDensScalingFactor = MpiWrapper::min( minCompDensScalingFactor ); - + scalingForLocalSystemSolution( subRegion, + dofManager, + maxDeltaPres, + maxDeltaCompDens, + maxDeltaTemp, + minPresScalingFactor, + minCompDensScalingFactor, + minTempScalingFactor, + localSolution ); string const massUnit = m_useMass ? "kg/m3" : "mol/m3"; GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, GEOS_FMT( " {}: Max well pressure change: {} Pa (before scaling)", @@ -1927,7 +1656,6 @@ CompositionalMultiphaseWell::scalingForSystemSolution( DomainPartition & domain, getName(), GEOS_FMT( "{:.{}f}", maxDeltaTemp, 3 ) ) ); } - GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, GEOS_FMT( " {}: Min well pressure scaling factor: {}", getName(), minPresScalingFactor ) ); @@ -1941,13 +1669,14 @@ CompositionalMultiphaseWell::scalingForSystemSolution( DomainPartition & domain, getName(), minTempScalingFactor ) ); } - return LvArray::math::max( scalingFactor, m_minScalingFactor ); } + + bool -CompositionalMultiphaseWell::checkWellSystemSolution( ElementSubRegionBase & subRegion, +CompositionalMultiphaseWell::checkWellSystemSolution( WellElementSubRegion & subRegion, DofManager const & dofManager, arrayView1d< real64 const > const & localSolution, real64 const scalingFactor ) @@ -2051,32 +1780,6 @@ CompositionalMultiphaseWell::checkWellSystemSolution( ElementSubRegionBase & sub return MpiWrapper::min( localCheck ); } -bool -CompositionalMultiphaseWell::checkSystemSolution( DomainPartition & domain, - DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution, - real64 const scalingFactor ) -{ - GEOS_MARK_FUNCTION; - - string const wellDofKey = dofManager.getKey( wellElementDofName() ); - integer globalCheck = 1; - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - integer localCheck = checkWellSystemSolution( subRegion, dofManager, localSolution, scalingFactor ); - globalCheck = MpiWrapper::min( localCheck ); - } ); - } ); - return globalCheck; -} - void CompositionalMultiphaseWell::computeWellPerforationRates( real64 const & time_n, real64 const & GEOS_UNUSED_PARAM( dt ), ElementRegionManager const & elemManager, @@ -2088,8 +1791,8 @@ void CompositionalMultiphaseWell::computeWellPerforationRates( real64 const & ti CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); PerforationData * const perforationData = subRegion.getPerforationData(); - WellControls const & wellControls = getWellControls( subRegion ); - if( wellControls.isWellOpen() && !m_keepVariablesConstantDuringInitStep ) + + if( isWellOpen() && !m_keepVariablesConstantDuringInitStep ) { string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); @@ -2102,13 +1805,13 @@ void CompositionalMultiphaseWell::computeWellPerforationRates( real64 const & ti PerforationFluxKernelFactory:: createAndLaunch< parallelDevicePolicy<> >( m_numComponents, m_numPhases, - flowSolver.getName(), + getFlowSolverName(), perforationData, subRegion, fluid, elemManager, - wellControls.isInjector(), - wellControls.isCrossflowEnabled()); + isInjector(), + isCrossflowEnabled()); } else { @@ -2116,12 +1819,12 @@ void CompositionalMultiphaseWell::computeWellPerforationRates( real64 const & ti PerforationFluxKernelFactory:: createAndLaunch< parallelDevicePolicy<> >( m_numComponents, m_numPhases, - flowSolver.getName(), + getFlowSolverName(), perforationData, subRegion, elemManager, - wellControls.isInjector(), - wellControls.isCrossflowEnabled() ); + isInjector(), + isCrossflowEnabled() ); } } else @@ -2141,31 +1844,6 @@ void CompositionalMultiphaseWell::computeWellPerforationRates( real64 const & ti } -void CompositionalMultiphaseWell::computePerforationRates( real64 const & time_n, - real64 const & dt, - DomainPartition & domain ) -{ - GEOS_MARK_FUNCTION; - GEOS_UNUSED_VAR( dt ); - forDiscretizationOnMeshTargets ( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - - // TODO: change the way we access the flowSolver here - - ElementRegionManager & elemManager = mesh.getElemManager(); - - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - computeWellPerforationRates( time_n, dt, elemManager, subRegion ); - - } ); - - } ); - -} void CompositionalMultiphaseWell::applyWellSystemSolution( DofManager const & dofManager, @@ -2245,84 +1923,7 @@ CompositionalMultiphaseWell::applyWellSystemSolution( DofManager const & dofMana } -void -CompositionalMultiphaseWell::applySystemSolution( DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution, - real64 const scalingFactor, - real64 const dt, - DomainPartition & domain ) -{ - - - DofManager::CompMask pressureMask( m_numDofPerWellElement, 0, 1 ); - DofManager::CompMask componentMask( m_numDofPerWellElement, 1, numFluidComponents()+1 ); - DofManager::CompMask connRateMask( m_numDofPerWellElement, numFluidComponents()+1, numFluidComponents()+2 ); - GEOS_UNUSED_VAR( dt ); - // update all the fields using the global damping coefficients - dofManager.addVectorToField( localSolution, - wellElementDofName(), - well::pressure::key(), - scalingFactor, - pressureMask ); - - dofManager.addVectorToField( localSolution, - wellElementDofName(), - well::globalCompDensity::key(), - scalingFactor, - componentMask ); - - dofManager.addVectorToField( localSolution, - wellElementDofName(), - well::mixtureConnectionRate::key(), - scalingFactor, - connRateMask ); - - if( isThermal() ) - { - DofManager::CompMask temperatureMask( m_numDofPerWellElement, numFluidComponents()+2, numFluidComponents()+3 ); - dofManager.addVectorToField( localSolution, - wellElementDofName(), - well::temperature::key(), - scalingFactor, - temperatureMask ); - - } - // if component density chopping is allowed, some component densities may be negative after the update - // these negative component densities are set to zero in this function - if( m_allowCompDensChopping ) - { - chopNegativeDensities( domain ); - } - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - // synchronize - FieldIdentifiers fieldsToBeSync; - if( isThermal() ) - { - fieldsToBeSync.addElementFields( { well::pressure::key(), - well::globalCompDensity::key(), - well::mixtureConnectionRate::key(), - well::temperature::key() }, - regionNames ); - } - else - { - fieldsToBeSync.addElementFields( { well::pressure::key(), - well::globalCompDensity::key(), - well::mixtureConnectionRate::key() }, - regionNames ); - } - CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, - mesh, - domain.getNeighbors(), - true ); - } ); - -} void CompositionalMultiphaseWell::chopNegativeDensities( WellElementSubRegion & subRegion ) { @@ -2352,95 +1953,44 @@ void CompositionalMultiphaseWell::chopNegativeDensities( WellElementSubRegion & } -void CompositionalMultiphaseWell::chopNegativeDensities( DomainPartition & domain ) -{ - integer const numComp = m_numComponents; - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - - ElementRegionManager & elemManager = mesh.getElemManager(); - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - arrayView1d< integer const > const & wellElemGhostRank = subRegion.ghostRank(); +void CompositionalMultiphaseWell::resetStateToBeginningOfStep( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) +{ - arrayView2d< real64, compflow::USD_COMP > const & wellElemCompDens = - subRegion.getField< well::globalCompDensity >(); + // get a reference to the primary variables on well elements + arrayView1d< real64 > const & wellElemPressure = + subRegion.getField< well::pressure >(); + arrayView1d< real64 const > const & wellElemPressure_n = + subRegion.getField< well::pressure_n >(); + wellElemPressure.setValues< parallelDevicePolicy<> >( wellElemPressure_n ); - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) - { - if( wellElemGhostRank[iwelem] < 0 ) - { - for( integer ic = 0; ic < numComp; ++ic ) - { - // we allowed for some densities to be slightly negative in CheckSystemSolution - // if the new density is negative, chop back to zero - if( wellElemCompDens[iwelem][ic] < 0 ) - { - wellElemCompDens[iwelem][ic] = 0; - } - } - } - } ); - } ); + if( isThermal() ) + { + // get a reference to the primary variables on well elements + arrayView1d< real64 > const & wellElemTemperature = + subRegion.getField< well::temperature >(); + arrayView1d< real64 const > const & wellElemTemperature_n = + subRegion.getField< well::temperature_n >(); + wellElemTemperature.setValues< parallelDevicePolicy<> >( wellElemTemperature_n ); + } + arrayView2d< real64, compflow::USD_COMP > const & wellElemGlobalCompDensity = + subRegion.getField< well::globalCompDensity >(); + arrayView2d< real64 const, compflow::USD_COMP > const & wellElemGlobalCompDensity_n = + subRegion.getField< well::globalCompDensity_n >(); + wellElemGlobalCompDensity.setValues< parallelDevicePolicy<> >( wellElemGlobalCompDensity_n ); - } ); -} + arrayView1d< real64 > const & connRate = + subRegion.getField< well::mixtureConnectionRate >(); + arrayView1d< real64 const > const & connRate_n = + subRegion.getField< well::mixtureConnectionRate_n >(); + connRate.setValues< parallelDevicePolicy<> >( connRate_n ); -void CompositionalMultiphaseWell::resetStateToBeginningOfStep( DomainPartition & domain ) -{ - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) + if( isWellOpen( ) ) { + updateSubRegionState( elemManager, subRegion ); + } - ElementRegionManager & elemManager = mesh.getElemManager(); - - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - // get a reference to the primary variables on well elements - arrayView1d< real64 > const & wellElemPressure = - subRegion.getField< well::pressure >(); - arrayView1d< real64 const > const & wellElemPressure_n = - subRegion.getField< well::pressure_n >(); - wellElemPressure.setValues< parallelDevicePolicy<> >( wellElemPressure_n ); - - if( isThermal() ) - { - // get a reference to the primary variables on well elements - arrayView1d< real64 > const & wellElemTemperature = - subRegion.getField< well::temperature >(); - arrayView1d< real64 const > const & wellElemTemperature_n = - subRegion.getField< well::temperature_n >(); - wellElemTemperature.setValues< parallelDevicePolicy<> >( wellElemTemperature_n ); - } - arrayView2d< real64, compflow::USD_COMP > const & wellElemGlobalCompDensity = - subRegion.getField< well::globalCompDensity >(); - arrayView2d< real64 const, compflow::USD_COMP > const & wellElemGlobalCompDensity_n = - subRegion.getField< well::globalCompDensity_n >(); - wellElemGlobalCompDensity.setValues< parallelDevicePolicy<> >( wellElemGlobalCompDensity_n ); - - arrayView1d< real64 > const & connRate = - subRegion.getField< well::mixtureConnectionRate >(); - arrayView1d< real64 const > const & connRate_n = - subRegion.getField< well::mixtureConnectionRate_n >(); - connRate.setValues< parallelDevicePolicy<> >( connRate_n ); - WellControls & wellControls = getWellControls( subRegion ); - - if( wellControls.isWellOpen( ) ) - { - updateSubRegionState( elemManager, subRegion ); - } - } ); - } ); } void CompositionalMultiphaseWell::assembleWellConstraintTerms( real64 const & time_n, @@ -2454,23 +2004,23 @@ void CompositionalMultiphaseWell::assembleWellConstraintTerms( real64 const & ti // the rank that owns the reference well element is responsible for the calculations below. - WellControls & wellControls = getWellControls( subRegion ); - if( !subRegion.isLocallyOwned() || !( wellControls.getWellStatus() == WellControls::Status::OPEN )) + + if( !subRegion.isLocallyOwned() || !( getWellStatus() == WellControls::Status::OPEN )) { return; } - if( wellControls.isProducer() ) + if( isProducer() ) { - wellControls.forSubGroups< MinimumBHPConstraint, ProductionConstraint< PhaseVolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, ProductionConstraint< VolumeRateConstraint >, - ProductionConstraint< LiquidRateConstraint > - >( [&]( auto & constraint ) + forSubGroups< MinimumBHPConstraint, ProductionConstraint< PhaseVolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, ProductionConstraint< VolumeRateConstraint >, + ProductionConstraint< LiquidRateConstraint > + >( [&]( auto & constraint ) { // Need to use name since there could be multiple constraints of the same type - if( constraint.getName() == wellControls.getCurrentConstraint()->getName()) + if( constraint.getName() == getCurrentConstraint()->getName()) { // found limiting constraint - constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); + constitutive::MultiFluidBase & fluidSeparator = getMultiFluidSeparator(); integer isThermal = fluidSeparator.isThermal(); integer const numComp = fluidSeparator.numFluidComponents(); geos::internal::kernelLaunchSelectorCompThermSwitch( numComp, isThermal, [&] ( auto NC, auto ISTHERMAL ) @@ -2479,7 +2029,7 @@ void CompositionalMultiphaseWell::assembleWellConstraintTerms( real64 const & ti integer constexpr IS_THERMAL = ISTHERMAL(); wellConstraintKernels::ConstraintHelper< NUM_COMP, IS_THERMAL >::assembleConstraintEquation( time_n, - wellControls, + *this, constraint, subRegion, dofManager.getKey( wellElementDofName() ), @@ -2492,15 +2042,15 @@ void CompositionalMultiphaseWell::assembleWellConstraintTerms( real64 const & ti } else { - wellControls.forSubGroups< MaximumBHPConstraint, InjectionConstraint< PhaseVolumeRateConstraint >, InjectionConstraint< MassRateConstraint >, - InjectionConstraint< VolumeRateConstraint >, - InjectionConstraint< LiquidRateConstraint > - >( [&]( auto & constraint ) + forSubGroups< MaximumBHPConstraint, InjectionConstraint< PhaseVolumeRateConstraint >, InjectionConstraint< MassRateConstraint >, + InjectionConstraint< VolumeRateConstraint >, + InjectionConstraint< LiquidRateConstraint > + >( [&]( auto & constraint ) { - if( constraint.getName() == wellControls.getCurrentConstraint()->getName()) + if( constraint.getName() == getCurrentConstraint()->getName()) { // found limiting constraint - constitutive::MultiFluidBase & fluidSeparator = wellControls.getMultiFluidSeparator(); + constitutive::MultiFluidBase & fluidSeparator = getMultiFluidSeparator(); integer isThermal = fluidSeparator.isThermal(); integer const numComp = fluidSeparator.numFluidComponents(); geos::internal::kernelLaunchSelectorCompThermSwitch( numComp, isThermal, [&] ( auto NC, auto ISTHERMAL ) @@ -2509,7 +2059,7 @@ void CompositionalMultiphaseWell::assembleWellConstraintTerms( real64 const & ti integer constexpr IS_THERMAL = ISTHERMAL(); wellConstraintKernels::ConstraintHelper< NUM_COMP, IS_THERMAL >::assembleConstraintEquation( time_n, - wellControls, + *this, constraint, subRegion, dofManager.getKey( wellElementDofName() ), @@ -2531,10 +2081,7 @@ void CompositionalMultiphaseWell::assembleWellPressureRelations( real64 const & { GEOS_MARK_FUNCTION; - - WellControls & wellControls = getWellControls( subRegion ); - - if( wellControls.isWellOpen( ) && !m_keepVariablesConstantDuringInitStep ) + if( isWellOpen( ) && !m_keepVariablesConstantDuringInitStep ) { string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); @@ -2583,32 +2130,7 @@ void CompositionalMultiphaseWell::assembleWellPressureRelations( real64 const & } -void CompositionalMultiphaseWell::assemblePressureRelations( real64 const & time_n, - real64 const & dt, - DomainPartition const & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) -{ - GEOS_MARK_FUNCTION; - GEOS_UNUSED_PARAM( dt ) - forDiscretizationOnMeshTargets ( domain.getMeshBodies(), [&] ( string const &, - MeshLevel const & mesh, - string_array const & regionNames ) - { - - ElementRegionManager const & elemManager = mesh.getElemManager(); - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion const & subRegion ) - { - - assembleWellPressureRelations( time_n, dt, subRegion, dofManager, localMatrix, localRhs ); - } ); - } ); - -} void CompositionalMultiphaseWell::saveState( WellElementSubRegion & subRegion ) { @@ -2659,264 +2181,238 @@ void CompositionalMultiphaseWell::saveState( WellElementSubRegion & subRegion ) void CompositionalMultiphaseWell::implicitStepSetup( real64 const & time_n, real64 const & dt, - DomainPartition & domain ) + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion ) { - WellSolverBase::implicitStepSetup( time_n, dt, domain ); + WellControls::implicitStepSetup( time_n, dt, elemManager, subRegion ); - forDiscretizationOnMeshTargets ( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) + if( isWellOpen() ) { + // get a reference to the primary variables on well elements + arrayView1d< real64 const > const & wellElemPressure = + subRegion.getField< fields::well::pressure >(); + arrayView2d< real64 const, compflow::USD_COMP > const & wellElemGlobalCompDensity = + subRegion.getField< fields::well::globalCompDensity >(); + arrayView1d< real64 const > const & wellElemTemperature = + subRegion.getField< fields::well::temperature >(); - ElementRegionManager & elemManager = mesh.getElemManager(); + arrayView1d< real64 > const & wellElemPressure_n = + subRegion.getField< fields::well::pressure_n >(); + wellElemPressure_n.setValues< parallelDevicePolicy<> >( wellElemPressure ); - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion & subRegion ) + if( isThermal() ) { + arrayView1d< real64 > const & wellElemTemperature_n = + subRegion.getField< fields::well::temperature_n >(); + wellElemTemperature_n.setValues< parallelDevicePolicy<> >( wellElemTemperature ); + } - WellControls & wellControls = getWellControls( subRegion ); - if( wellControls.isWellOpen() ) - { - // get a reference to the primary variables on well elements - arrayView1d< real64 const > const & wellElemPressure = - subRegion.getField< fields::well::pressure >(); - arrayView2d< real64 const, compflow::USD_COMP > const & wellElemGlobalCompDensity = - subRegion.getField< fields::well::globalCompDensity >(); - arrayView1d< real64 const > const & wellElemTemperature = - subRegion.getField< fields::well::temperature >(); - - arrayView1d< real64 > const & wellElemPressure_n = - subRegion.getField< fields::well::pressure_n >(); - wellElemPressure_n.setValues< parallelDevicePolicy<> >( wellElemPressure ); - - if( isThermal() ) - { - arrayView1d< real64 > const & wellElemTemperature_n = - subRegion.getField< fields::well::temperature_n >(); - wellElemTemperature_n.setValues< parallelDevicePolicy<> >( wellElemTemperature ); - } + arrayView2d< real64, compflow::USD_COMP > const & wellElemGlobalCompDensity_n = + subRegion.getField< fields::well::globalCompDensity_n >(); + wellElemGlobalCompDensity_n.setValues< parallelDevicePolicy<> >( wellElemGlobalCompDensity ); - arrayView2d< real64, compflow::USD_COMP > const & wellElemGlobalCompDensity_n = - subRegion.getField< fields::well::globalCompDensity_n >(); - wellElemGlobalCompDensity_n.setValues< parallelDevicePolicy<> >( wellElemGlobalCompDensity ); + arrayView1d< real64 const > const & connRate = + subRegion.getField< fields::well::mixtureConnectionRate >(); + arrayView1d< real64 > const & connRate_n = + subRegion.getField< fields::well::mixtureConnectionRate_n >(); + connRate_n.setValues< parallelDevicePolicy<> >( connRate ); - arrayView1d< real64 const > const & connRate = - subRegion.getField< fields::well::mixtureConnectionRate >(); - arrayView1d< real64 > const & connRate_n = - subRegion.getField< fields::well::mixtureConnectionRate_n >(); - connRate_n.setValues< parallelDevicePolicy<> >( connRate ); + arrayView2d< real64 const, compflow::USD_PHASE > const wellElemPhaseVolFrac = + subRegion.getField< fields::well::phaseVolumeFraction >(); + arrayView2d< real64, compflow::USD_PHASE > const wellElemPhaseVolFrac_n = + subRegion.getField< fields::well::phaseVolumeFraction_n >(); + wellElemPhaseVolFrac_n.setValues< parallelDevicePolicy<> >( wellElemPhaseVolFrac ); - arrayView2d< real64 const, compflow::USD_PHASE > const wellElemPhaseVolFrac = - subRegion.getField< fields::well::phaseVolumeFraction >(); - arrayView2d< real64, compflow::USD_PHASE > const wellElemPhaseVolFrac_n = - subRegion.getField< fields::well::phaseVolumeFraction_n >(); - wellElemPhaseVolFrac_n.setValues< parallelDevicePolicy<> >( wellElemPhaseVolFrac ); + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + fluid.saveConvergedState(); - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); - fluid.saveConvergedState(); + validateWellConstraints( time_n, dt, subRegion ); - validateWellConstraints( time_n, dt, subRegion ); + updateSubRegionState( elemManager, subRegion ); + } - updateSubRegionState( elemManager, subRegion ); - } - } ) - ; - } ); } void CompositionalMultiphaseWell::implicitStepComplete( real64 const & time_n, real64 const & dt, - DomainPartition & domain ) + WellElementSubRegion const & subRegion ) { - WellSolverBase::implicitStepComplete( time_n, dt, domain ); + //WellSolverBase::implicitStepComplete( time_n, dt, subRegion ); if( getLogLevel() > 0 ) { - printRates( time_n, dt, domain ); + printRates( time_n, dt, subRegion ); } } void CompositionalMultiphaseWell::printRates( real64 const & time_n, real64 const & dt, - DomainPartition & domain ) + WellElementSubRegion const & subRegion ) { - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - ElementRegionManager & elemManager = mesh.getElemManager(); + integer const numPhase = m_numPhases; + integer const numComp = m_numComponents; + integer const numPerf = subRegion.getPerforationData()->size(); - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - integer const numPhase = m_numPhases; - integer const numComp = m_numComponents; - integer const numPerf = subRegion.getPerforationData()->size(); - // control data - WellControls const & wellControls = getWellControls( subRegion ); - stdVector< double > compRate( numComp, 0.0 ); - if( m_writeCSV > 0 && wellControls.isWellOpen( ) ) - { - arrayView2d< real64 > const compPerfRate = subRegion.getPerforationData()->getField< fields::well::compPerforationRate >(); + stdVector< double > compRate( numComp, 0.0 ); + if( m_writeCSV > 0 && isWellOpen( ) ) + { + arrayView2d< real64 const > const & compPerfRate = subRegion.getPerforationData()->getField< fields::well::compPerforationRate >(); - // bring everything back to host, capture the scalars by reference - forAll< serialPolicy >( 1, [&numComp, - &numPerf, - compPerfRate, - &compRate] ( localIndex const ) - { - for( integer ic = 0; ic < numComp; ++ic ) - { - for( integer iperf = 0; iperf < numPerf; iperf++ ) - { - compRate[ic] += compPerfRate[iperf][ic]; - } - } - } ); - for( integer ic = 0; ic < numComp; ++ic ) + // bring everything back to host, capture the scalars by reference + forAll< serialPolicy >( 1, [&numComp, + &numPerf, + compPerfRate, + &compRate] ( localIndex const ) + { + for( integer ic = 0; ic < numComp; ++ic ) + { + for( integer iperf = 0; iperf < numPerf; iperf++ ) { - compRate[ic] = MpiWrapper::sum( compRate[ic] ); + compRate[ic] += compPerfRate[iperf][ic]; } } + } ); + for( integer ic = 0; ic < numComp; ++ic ) + { + compRate[ic] = MpiWrapper::sum( compRate[ic] ); + } + } - // the rank that owns the reference well element is responsible for the calculations below. - if( !subRegion.isLocallyOwned() ) - { - return; - } + // the rank that owns the reference well element is responsible for the calculations below. + if( !subRegion.isLocallyOwned() ) + { + return; + } - string const wellControlsName = wellControls.getName(); + string const wellControlsName = getName(); - // format: time,total_rate,total_vol_rate,phase0_vol_rate,phase1_vol_rate,... - std::ofstream outputFile; - if( m_writeCSV > 0 ) + // format: time,total_rate,total_vol_rate,phase0_vol_rate,phase1_vol_rate,... + std::ofstream outputFile; + if( m_writeCSV > 0 ) + { + outputFile.open( m_ratesOutputDir + "/" + wellControlsName + ".csv", std::ios_base::app ); + outputFile << time_n << "," << dt; + } + + if( getWellStatus() == WellControls::Status::CLOSED ) + { + GEOS_LOG( GEOS_FMT( "{}: well is shut", wellControlsName ) ); + if( outputFile.is_open()) + { + // print all zeros in the rates file + outputFile << ",0.0,0.0,0.0"; + for( integer ip = 0; ip < numPhase; ++ip ) { - outputFile.open( m_ratesOutputDir + "/" + wellControlsName + ".csv", std::ios_base::app ); - outputFile << time_n << "," << dt; + outputFile << ",0.0"; } - - if( wellControls.getWellStatus() == WellControls::Status::CLOSED ) + for( integer ic = 0; ic < numComp; ++ic ) { - GEOS_LOG( GEOS_FMT( "{}: well is shut", wellControlsName ) ); - if( outputFile.is_open()) - { - // print all zeros in the rates file - outputFile << ",0.0,0.0,0.0"; - for( integer ip = 0; ip < numPhase; ++ip ) - { - outputFile << ",0.0"; - } - for( integer ic = 0; ic < numComp; ++ic ) - { - outputFile << ",0.0"; - } - outputFile << std::endl; - outputFile.close(); - } - return; + outputFile << ",0.0"; } + outputFile << std::endl; + outputFile.close(); + } + return; + } - localIndex const iwelemRef = subRegion.getTopWellElementIndex(); - string const massUnit = m_useMass ? "kg" : "mol"; - - // subRegion data - - arrayView1d< real64 const > const & connRate = - subRegion.getField< well::mixtureConnectionRate >(); - - integer const useSurfaceConditions = wellControls.useSurfaceConditions(); - - real64 const & currentBHP = - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() ); - arrayView1d< real64 const > const & currentPhaseVolRate = - wellControls.getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ); - real64 const & currentTotalVolRate = - wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() ); - - // bring everything back to host, capture the scalars by reference - forAll< serialPolicy >( 1, [&numPhase, - &numComp, - &useSurfaceConditions, - ¤tBHP, - connRate, - ¤tTotalVolRate, - currentPhaseVolRate, - &compRate, - &iwelemRef, - &wellControlsName, - &massUnit, - &outputFile] ( localIndex const ) + localIndex const iwelemRef = subRegion.getTopWellElementIndex(); + string const massUnit = m_useMass ? "kg" : "mol"; + + // subRegion data + + arrayView1d< real64 const > const & connRate = + subRegion.getField< well::mixtureConnectionRate >(); + + integer const useSurfaceCond = useSurfaceConditions(); + + real64 const & currentBHP = + getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() ); + arrayView1d< real64 const > const & currentPhaseVolRate = + getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ); + real64 const & currentTotalVolRate = + getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() ); + + // bring everything back to host, capture the scalars by reference + forAll< serialPolicy >( 1, [&numPhase, + &numComp, + &useSurfaceCond, + ¤tBHP, + connRate, + ¤tTotalVolRate, + currentPhaseVolRate, + &compRate, + &iwelemRef, + &wellControlsName, + &massUnit, + &outputFile] ( localIndex const ) + { + string const conditionKey = useSurfaceCond ? "surface" : "reservoir"; + string const unitKey = useSurfaceCond ? "s" : "r"; + + real64 const currentTotalRate = connRate[iwelemRef]; + GEOS_LOG( GEOS_FMT( "{}: BHP (at the specified reference elevation): {} Pa", + wellControlsName, currentBHP ) ); + GEOS_LOG( GEOS_FMT( "{}: Total rate: {} {}/s; total {} volumetric rate: {} {}m3/s", + wellControlsName, currentTotalRate, massUnit, conditionKey, currentTotalVolRate, unitKey ) ); + for( integer ip = 0; ip < numPhase; ++ip ) + GEOS_LOG( GEOS_FMT( "{}: Phase {} {} volumetric rate: {} {}m3/s", + wellControlsName, ip, conditionKey, currentPhaseVolRate[ip], unitKey ) ); + if( outputFile.is_open()) + { + outputFile << "," << currentBHP; + outputFile << "," << currentTotalRate << "," << currentTotalVolRate; + for( integer ip = 0; ip < numPhase; ++ip ) { - string const conditionKey = useSurfaceConditions ? "surface" : "reservoir"; - string const unitKey = useSurfaceConditions ? "s" : "r"; - - real64 const currentTotalRate = connRate[iwelemRef]; - GEOS_LOG( GEOS_FMT( "{}: BHP (at the specified reference elevation): {} Pa", - wellControlsName, currentBHP ) ); - GEOS_LOG( GEOS_FMT( "{}: Total rate: {} {}/s; total {} volumetric rate: {} {}m3/s", - wellControlsName, currentTotalRate, massUnit, conditionKey, currentTotalVolRate, unitKey ) ); - for( integer ip = 0; ip < numPhase; ++ip ) - GEOS_LOG( GEOS_FMT( "{}: Phase {} {} volumetric rate: {} {}m3/s", - wellControlsName, ip, conditionKey, currentPhaseVolRate[ip], unitKey ) ); - if( outputFile.is_open()) - { - outputFile << "," << currentBHP; - outputFile << "," << currentTotalRate << "," << currentTotalVolRate; - for( integer ip = 0; ip < numPhase; ++ip ) - { - outputFile << "," << currentPhaseVolRate[ip]; - } - for( integer ic = 0; ic < numComp; ++ic ) - { - outputFile << "," << compRate[ic]; - } - outputFile << std::endl; - outputFile.close(); - } - } ); - } ); + outputFile << "," << currentPhaseVolRate[ip]; + } + for( integer ic = 0; ic < numComp; ++ic ) + { + outputFile << "," << compRate[ic]; + } + outputFile << std::endl; + outputFile.close(); + } } ); + } bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, WellElementSubRegion & subRegion ) { - WellControls & wellControls = getWellControls( subRegion ); + // create list of all constraints to process std::vector< WellConstraintBase * > constraintList; - if( wellControls.isProducer() ) + if( isProducer() ) { - constraintList = wellControls.getProdRateConstraints(); + constraintList = getProdRateConstraints(); // Solve minimum bhp constraint first - constraintList.insert( constraintList.begin(), wellControls.getMinBHPConstraint() ); + constraintList.insert( constraintList.begin(), getMinBHPConstraint() ); } else { - constraintList = wellControls.getInjRateConstraints(); + constraintList = getInjRateConstraints(); // Solve maximum bhp constraint first; - constraintList.insert( constraintList.begin(), wellControls.getMaxBHPConstraint() ); + constraintList.insert( constraintList.begin(), getMaxBHPConstraint() ); } // Get current constraint WellConstraintBase * limitingConstraint = nullptr; for( auto & constraint : constraintList ) { - if( constraint->getName() == wellControls.getCurrentConstraint()->getName()) + if( constraint->getName() == getCurrentConstraint()->getName()) { limitingConstraint = constraint; // tjb. this is likely not needed. set in update state - constraint->setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); - constraint->setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( + constraint->setBHP ( getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); + constraint->setPhaseVolumeRates ( getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); - constraint->setTotalVolumeRate ( wellControls.getReference< real64 >( + constraint->setTotalVolumeRate ( getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); - constraint->setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); + constraint->setMassRate( getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << limitingConstraint->phaseVolumeRates() << " " << @@ -2934,14 +2430,14 @@ bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, if( constraint->checkViolation( *limitingConstraint, time_n ) ) { limitingConstraint = constraint; - wellControls.setControl( static_cast< WellControls::Control >(constraint->getControl()) ); // tjb old - wellControls.setCurrentConstraint( constraint ); - constraint->setBHP ( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); - constraint->setPhaseVolumeRates ( wellControls.getReference< array1d< real64 > >( + setControl( static_cast< WellControls::Control >(constraint->getControl()) ); // tjb old + setCurrentConstraint( constraint ); + constraint->setBHP ( getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentBHPString() )); + constraint->setPhaseVolumeRates ( getReference< array1d< real64 > >( CompositionalMultiphaseWell::viewKeyStruct::currentPhaseVolRateString() ) ); - constraint->setTotalVolumeRate ( wellControls.getReference< real64 >( + constraint->setTotalVolumeRate ( getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentTotalVolRateString() )); - constraint->setMassRate( wellControls.getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); + constraint->setMassRate( getReference< real64 >( CompositionalMultiphaseWell::viewKeyStruct::currentMassRateString() )); GEOS_LOG_RANK_IF ( subRegion.isLocallyOwned(), " Well " << subRegion.getName() << " Control switch " << constraint->getName() << " " << constraint->getConstraintValue( time_n ) ); } @@ -2954,5 +2450,5 @@ bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, return true; } -REGISTER_CATALOG_ENTRY( PhysicsSolverBase, CompositionalMultiphaseWell, string const &, Group * const ) + } // namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp index 0ab2396806c..265d55db0b1 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp @@ -26,7 +26,7 @@ #include "physicsSolvers/fluidFlow/CompositionalMultiphaseBase.hpp" #include "physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp" -#include "physicsSolvers/fluidFlow/wells/WellSolverBase.hpp" +#include "physicsSolvers/fluidFlow/wells/WellControls.hpp" namespace geos { @@ -41,7 +41,7 @@ class MultiFluidBase; * * A compositional multiphase well solver */ -class CompositionalMultiphaseWell : public WellSolverBase +class CompositionalMultiphaseWell : public WellControls { public: @@ -73,22 +73,77 @@ class CompositionalMultiphaseWell : public WellSolverBase */ virtual ~CompositionalMultiphaseWell() override = default; + + void registerWellDataOnMesh( WellElementSubRegion & subRegion ) override; /** - * @brief name of the node manager in the object catalog - * @return string that contains the catalog name to generate a new NodeManager object through the object catalog. + * @defgroup WellManager Interface Functions + * + * These functions provide the primary interface that is required for derived classes + * The "Well" versions apply to individual well subRegions, whereas the others apply to all wells */ - static string catalogName() { return "CompositionalMultiphaseWell"; } + /**@{*/ /** - * @copydoc PhysicsSolverBase::getCatalogName() + * * @brief Initialize well for the beginning of a simulation or restart + * @param domain the domain + * @param mesh the mesh level + * @param subRegion the well subRegion */ - string getCatalogName() const override { return catalogName(); } + virtual void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n )override; /** - * @copydoc PhysicsSolverBase::registerDataOnMesh() + * @brief Function to evaluate well constraints after applying the solution update + * @param time_n the time at the beginning of the time step + * @param subRegion the well subRegion + * @return true if all constraints are satisfied, false otherwise + */ + virtual bool evaluateConstraints( real64 const & time_n, + WellElementSubRegion & subRegion ) override; + /** + * @copydoc WellControls::assembleWellAccumulationTerms() + */ + virtual void assembleWellAccumulationTerms( real64 const & time, + real64 const & dt, + WellElementSubRegion & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; + /** + * @copydoc WellControls::assembleWellPressureRelations() */ - virtual void registerDataOnMesh( Group & meshBodies ) override; + virtual void assembleWellPressureRelations( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; + /** + * @copydoc WellControls::assembleWellConstraintTerms() + */ + virtual void assembleWellConstraintTerms( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; + /** + * @copydoc WellControls::computeWellPerforationRates() + */ + virtual void computeWellPerforationRates( real64 const & time_n, + real64 const & GEOS_UNUSED_PARAM( dt ), + ElementRegionManager const & elemManager, + WellElementSubRegion & subRegion ) override; + /** + * @copydoc WellControls::assembleFluxTerms() + */ + virtual void assembleWellFluxTerms( real64 const & time, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; + /**@}*/ /** * @defgroup Solver Interface Functions * @@ -98,58 +153,55 @@ class CompositionalMultiphaseWell : public WellSolverBase /**@{*/ /** - * @copydoc PhysicsSolverBase::calculateResidualNorm() + * @copydoc WellControls::calculateResidualNorm() */ - virtual real64 - calculateResidualNorm( real64 const & time_n, - real64 const & dt, - DomainPartition const & domain, - DofManager const & dofManager, - arrayView1d< real64 const > const & localRhs ) override; + + virtual array1d< real64 > + calculateLocalWellResidualNorm( real64 const & time_n, + real64 const & dt, + NonlinearSolverParameters const & nonlinearSolverParameters, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs )override; + virtual real64 calculateWellResidualNorm( real64 const & time_n, real64 const & dt, + NonlinearSolverParameters const & nonlinearSolverParameters, WellElementSubRegion const & subRegion, DofManager const & dofManager, arrayView1d< real64 const > const & localRhs ) override; /** - * @copydoc PhysicsSolverBase::scalingForSystemSolution() + * @copydoc WellControls::scalingForSystemSolution() */ - virtual real64 - scalingForSystemSolution( DomainPartition & domain, - DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution ) override; + void scalingForLocalSystemSolution ( WellElementSubRegion & subRegion, + DofManager const & dofManager, + real64 & maxDeltaPres, + real64 & maxDeltaCompDens, + real64 & maxDeltaTemp, + real64 & minPresScalingFactor, + real64 & minCompDensScalingFactor, + real64 & minTempScalingFactor, + arrayView1d< real64 const > const & localSolution ); - virtual real64 - scalingForWellSystemSolution( ElementSubRegionBase & subRegion, - DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution ) override; + virtual real64 scalingForWellSystemSolution( WellElementSubRegion & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution ) override; /** - * @copydoc PhysicsSolverBase::checkSystemSolution() + * @copydoc WellControls::checkSystemSolution() */ virtual bool - checkSystemSolution( DomainPartition & domain, - DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution, - real64 const scalingFactor ) override; - virtual bool - checkWellSystemSolution( ElementSubRegionBase & subRegion, + checkWellSystemSolution( WellElementSubRegion & subRegion, DofManager const & dofManager, arrayView1d< real64 const > const & localSolution, real64 const scalingFactor ) override; /** - * @copydoc PhysicsSolverBase::applySystemSolution() + * @copydoc WellControls::applyWellSystemSolution() */ - virtual void - applySystemSolution( DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution, - real64 const scalingFactor, - real64 const dt, - DomainPartition & domain ) override; virtual void applyWellSystemSolution( DofManager const & dofManager, @@ -160,18 +212,24 @@ class CompositionalMultiphaseWell : public WellSolverBase MeshLevel & mesh, WellElementSubRegion & subRegion ) override; - virtual void - resetStateToBeginningOfStep( DomainPartition & domain ) override; + virtual void resetStateToBeginningOfStep( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) override; - virtual void - implicitStepSetup( real64 const & time, - real64 const & dt, - DomainPartition & domain ) override; + virtual void implicitStepSetup( real64 const & time_n, + real64 const & GEOS_UNUSED_PARAM( dt ), + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion )override; virtual void implicitStepComplete( real64 const & time, real64 const & dt, - DomainPartition & domain ) override; + WellElementSubRegion const & subRegion ) override; + virtual void initializeWellPostInitialConditionsPreSubGroups( WellElementSubRegion & subRegion )override; + + virtual void printRates( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion ) override; + + virtual real64 updateSubRegionState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) override; /**@}*/ @@ -202,7 +260,8 @@ class CompositionalMultiphaseWell : public WellSolverBase void updateFluidModel( WellElementSubRegion & subRegion ); /** - * @brief Update well separator using current values of pressure and composition at the reference element + * @brief Update well separator using current values of pressure and composition at the reference + * element * @param elemManager the element region manager */ @@ -229,35 +288,12 @@ class CompositionalMultiphaseWell : public WellSolverBase */ void updateTotalMassDensity( WellElementSubRegion & subRegion ) const; - /** - * @brief Recompute the perforation rates for all the wells - * @param domain the domain containing the mesh and fields - */ - virtual void computeWellPerforationRates( real64 const & time_n, - real64 const & GEOS_UNUSED_PARAM( dt ), - ElementRegionManager const & elemManager, - WellElementSubRegion & subRegion )override; - - /** - * @brief Recompute the perforation rates for all the wells - * @param domain the domain containing the mesh and fields - */ - virtual void computePerforationRates( real64 const & time_n, - real64 const & dt, DomainPartition & domain ) override; - /** * @brief Recompute all dependent quantities from primary variables (including constitutive models) * @param subRegion the well subregion containing all the primary and dependent fields */ virtual real64 updateWellState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) override; - /** - * @brief Recompute all dependent quantities from primary variables (including constitutive models) - * @param domain the domain containing the mesh and fields - */ - virtual void updateState( DomainPartition & domain ) override; - - virtual real64 updateSubRegionState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) override; virtual string wellElementDofName() const override { return viewKeyStruct::dofFieldString(); } @@ -269,76 +305,6 @@ class CompositionalMultiphaseWell : public WellSolverBase integer useTotalMassEquation() const { return m_useTotalMassEquation; } - - /** - * @copydoc WellSolverBase::assembleFluxTerms() - */ - - virtual void assembleFluxTerms( real64 const & time_n, - real64 const & dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs )override; - - /** - * @copydoc WellSolverBase::assembleFluxTerms() - */ - virtual void assembleWellFluxTerms( real64 const & time, - real64 const & dt, - WellElementSubRegion const & subRegion, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) override; - - /** - * @copydoc WellSolverBase::assembleAccumulationTerms() - */ - virtual void assembleAccumulationTerms( real64 const & time_n, - real64 const & dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) override; - /** - * @copydoc WellSolverBase::assembleWellAccumulationTerms() - */ - virtual void assembleWellAccumulationTerms( real64 const & time, - real64 const & dt, - WellElementSubRegion & subRegion, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) override; - - /** - * @copydoc WellSolverBase::assembleWellConstraintTerms() - */ - virtual void assembleWellConstraintTerms( real64 const & time_n, - real64 const & dt, - WellElementSubRegion const & subRegion, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) override; - - /** - * @copydoc WellSolverBase::assemblePressureRelations() - */ - virtual void assemblePressureRelations( real64 const & time_n, - real64 const & dt, - DomainPartition const & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) override; - /** - * @copydoc WellSolverBase::assembleWellPressureRelations() - */ - virtual void assembleWellPressureRelations( real64 const & time_n, - real64 const & dt, - WellElementSubRegion const & subRegion, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) override; - /** * @brief Sets all the negative component densities (if any) to zero. * @param domain the physical domain object @@ -347,14 +313,8 @@ class CompositionalMultiphaseWell : public WellSolverBase void chopNegativeDensities( WellElementSubRegion & subRegion ); - /** - * @brief Initialize all the primary and secondary variables in all the wells - * @param domain the domain containing the well manager to access individual wells - */ - void initializeWells( DomainPartition & domain, real64 const & time_n ) override; - void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) override; - struct viewKeyStruct : WellSolverBase::viewKeyStruct + struct viewKeyStruct : WellControls::viewKeyStruct { static constexpr char const * dofFieldString() { return "compositionalWellVars"; } @@ -399,7 +359,7 @@ class CompositionalMultiphaseWell : public WellSolverBase virtual void initializePostInitialConditionsPreSubGroups() override; void saveState( WellElementSubRegion & subRegion ); - virtual void postRestartInitialization() override final; + virtual void postRestartInitialization( )override; /** * @brief Checks fluild model compatibility and validity @@ -425,20 +385,9 @@ class CompositionalMultiphaseWell : public WellSolverBase /** * @brief Create well separator */ - void createSeparator(); + virtual void createSeparator( WellElementSubRegion & subRegion ) override; - void printRates( real64 const & time_n, - real64 const & dt, - DomainPartition & domain ) override; - /** - * @brief Function to evaluate well constraints after applying the solution update - * @param time_n the time at the beginning of the time step - * @param subRegion the well subRegion - * @return true if all constraints are satisfied, false otherwise - */ - virtual bool evaluateConstraints( real64 const & time_n, - WellElementSubRegion & subRegion ) override; private: diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index 4bf938cd3b7..34eebf4550d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -54,7 +54,7 @@ using namespace singlePhaseWellKernels; SinglePhaseWell::SinglePhaseWell( const string & name, Group * const parent ): - WellSolverBase( name, parent ) + WellControls( name, parent ) { m_numDofPerWellElement = 2; m_numDofPerResElement = 1; @@ -67,64 +67,59 @@ SinglePhaseWell::SinglePhaseWell( const string & name, setDescription( "Flag indicating if negative pressure is allowed" ); } -void SinglePhaseWell::registerDataOnMesh( Group & meshBodies ) +void SinglePhaseWell::registerWellDataOnMesh( WellElementSubRegion & subRegion ) { - WellSolverBase::registerDataOnMesh( meshBodies ); +/// WellControls::registerDataOnMesh( meshBodies ); replaced by following 2 lines - // loop over the wells - forDiscretizationOnMeshTargets( meshBodies, [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) + setConstitutiveNames ( subRegion ); + + DomainPartition const & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); + ConstitutiveManager const & cm = domain.getConstitutiveManager(); + if( m_referenceFluidModelName.empty() ) { + m_referenceFluidModelName = getConstitutiveName< MultiFluidBase >( subRegion ); + } - ElementRegionManager & elemManager = mesh.getElemManager(); + subRegion.registerField< well::connectionRate_n >( getName() ); + subRegion.registerField< well::connectionRate >( getName() ); - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - subRegion.registerField< well::connectionRate_n >( getName() ); - subRegion.registerField< well::connectionRate >( getName() ); - - PerforationData & perforationData = *subRegion.getPerforationData(); - perforationData.registerField< well::perforationRate >( getName() ); - perforationData.registerField< well::dPerforationRate >( getName() ). - reference().resizeDimension< 1, 2 >( 2, 2 ); - if( isThermal() ) - { - perforationData.registerField< well::energyPerforationFlux >( getName() ); - perforationData.registerField< well::dEnergyPerforationFlux >( getName() ). - reference().resizeDimension< 1, 2 >( 2, 2 ); - } + PerforationData & perforationData = *subRegion.getPerforationData(); + perforationData.registerField< well::perforationRate >( getName() ); + perforationData.registerField< well::dPerforationRate >( getName() ). + reference().resizeDimension< 1, 2 >( 2, 2 ); + if( isThermal() ) + { + perforationData.registerField< well::energyPerforationFlux >( getName() ); + perforationData.registerField< well::dEnergyPerforationFlux >( getName() ). + reference().resizeDimension< 1, 2 >( 2, 2 ); + } - WellControls & wellControls = getWellControls( subRegion ); - wellControls.registerWrapper< real64 >( viewKeyStruct::currentBHPString() ); - wellControls.registerWrapper< array1d< real64 > >( viewKeyStruct::dCurrentBHPString() ). - setSizedFromParent( 0 ). - reference().resizeDimension< 0 >( 2 + isThermal() ); // dP, dT , dQ + registerWrapper< real64 >( viewKeyStruct::currentBHPString() ); - wellControls.registerWrapper< real64 >( viewKeyStruct::currentVolRateString() ); - wellControls.registerWrapper< array1d< real64 > >( viewKeyStruct::dCurrentVolRateString() ). - setSizedFromParent( 0 ). - reference().resizeDimension< 0 >( 2 + isThermal() ); // dP, dT, dQ + registerWrapper< array1d< real64 > >( viewKeyStruct::dCurrentBHPString() ). + setSizedFromParent( 0 ). + reference().resizeDimension< 0 >( 2 + isThermal() ); // dP, dT , dQ + + registerWrapper< real64 >( viewKeyStruct::currentVolRateString() ); + registerWrapper< array1d< real64 > >( viewKeyStruct::dCurrentVolRateString() ). + setSizedFromParent( 0 ). + reference().resizeDimension< 0 >( 2 + isThermal() ); // dP, dT, dQ + + // write rates output header + if( m_writeCSV > 0 && subRegion.isLocallyOwned()) + { + string const fileName = GEOS_FMT( "{}/{}.csv", m_ratesOutputDir, getName() ); + string const conditionKey = useSurfaceConditions() ? "surface" : "reservoir"; + string const unitKey = useSurfaceConditions() ? "s" : "r"; + // format: time,bhp,total_rate,total_vol_rate + makeDirsForPath( m_ratesOutputDir ); + GEOS_LOG( GEOS_FMT( "{}: Rates CSV generated at {}", getName(), fileName ) ); + std::ofstream outputFile( fileName ); + outputFile << "Time [s],BHP [Pa],Total rate [kg/s],Total " << conditionKey << " volumetric rate ["< 0 && subRegion.isLocallyOwned()) - { - string const fileName = GEOS_FMT( "{}/{}.csv", m_ratesOutputDir, wellControls.getName() ); - integer const useSurfaceConditions = wellControls.useSurfaceConditions(); - string const conditionKey = useSurfaceConditions ? "surface" : "reservoir"; - string const unitKey = useSurfaceConditions ? "s" : "r"; - // format: time,bhp,total_rate,total_vol_rate - makeDirsForPath( m_ratesOutputDir ); - GEOS_LOG( GEOS_FMT( "{}: Rates CSV generated at {}", getName(), fileName ) ); - std::ofstream outputFile( fileName ); - outputFile << "Time [s],BHP [Pa],Total rate [kg/s],Total " << conditionKey << " volumetric rate ["<( getFlowSolverName() ); string_array const & targetRegionsNames = flowSolver.getTargetRegionNames(); auto const pos = std::find( targetRegionsNames.begin(), targetRegionsNames.end(), regionName ); GEOS_ERROR_IF( pos == targetRegionsNames.end(), GEOS_FMT( "{}: Region {} is not a target of the reservoir solver and cannot be used for referenceReservoirRegion in WellControl {}.", - getDataContext(), regionName, wellControls.getName() ) ); + getDataContext(), regionName, getName() ) ); } } - // tjb WellControls::Control currentControl = wellControls.getControl(); -#if 0 - real64 const targetTotalRate = wellControls.getTargetTotalRate( time_n ); - real64 const targetPhaseRate = wellControls.getTargetPhaseRate( time_n ); - GEOS_THROW_IF( currentControl == WellControls::Control::PHASEVOLRATE, - "WellControls " << wellControls.getDataContext() << - ": Phase rate control is not available for SinglePhaseWell", - InputError, wellControls.getDataContext() ); - // The user always provides positive rates, but these rates are later multiplied by -1 internally for producers - GEOS_THROW_IF( ( ( wellControls.isInjector() && targetTotalRate < 0.0 ) || - ( wellControls.isProducer() && targetTotalRate > 0.0) ), - "WellControls " << wellControls.getDataContext() << - ": Target total rate cannot be negative", - InputError, wellControls.getDataContext() ); - GEOS_THROW_IF( !isZero( targetPhaseRate ), - "WellControls " << wellControls.getDataContext() << - ": Target phase rate cannot be used for SinglePhaseWell", - InputError, wellControls.getDataContext() ); -#endif } +void SinglePhaseWell::initializeWellPostInitialConditionsPreSubGroups( WellElementSubRegion & subRegion ) +{ + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + + constitutive::SingleFluidBase & fluid = subRegion.getConstitutiveModel< constitutive::SingleFluidBase >( fluidName ); + + createSeparator( subRegion ); +} void SinglePhaseWell::initializePostInitialConditionsPreSubGroups() { - WellSolverBase::initializePostInitialConditionsPreSubGroups(); - createSeparator(); + //WellControl::initializePostInitialConditionsPreSubGroups(); + } -void SinglePhaseWell::createSeparator() +void SinglePhaseWell::postRestartInitialization( ) { - DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - // loop over the wells - mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - SingleFluidBase & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); - // setup fluid separator - WellControls & wellControls = getWellControls( subRegion ); - string const fluidSeparatorName = wellControls.getName() + "Separator"; - std::unique_ptr< constitutive::ConstitutiveBase > fluidSeparatorPtr = fluid.deliverClone( fluidSeparatorName, &wellControls ); - fluidSeparatorPtr->allocateConstitutiveData( wellControls, 1 ); - fluidSeparatorPtr->resize( 1 ); - wellControls.setFluidSeparator( std::move( fluidSeparatorPtr )); - } ); - } ); + // setup fluid separator + constitutive::SingleFluidBase & fluidSeparator = getSingleFluidSeparator(); + fluidSeparator.allocateConstitutiveData( *this, 1 ); + fluidSeparator.resize( 1 ); + +} +void SinglePhaseWell::createSeparator( WellElementSubRegion & subRegion ) +{ + + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + SingleFluidBase & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); + // setup fluid separator + + string const fluidSeparatorName = getName() + "Separator"; + std::unique_ptr< constitutive::ConstitutiveBase > fluidSeparatorPtr = fluid.deliverClone( fluidSeparatorName, this ); + fluidSeparatorPtr->allocateConstitutiveData( *this, 1 ); + fluidSeparatorPtr->resize( 1 ); + setFluidSeparator( std::move( fluidSeparatorPtr )); + } void SinglePhaseWell::updateBHPForConstraint( WellElementSubRegion & subRegion ) @@ -245,14 +228,13 @@ void SinglePhaseWell::updateBHPForConstraint( WellElementSubRegion & subRegion ) // control data - WellControls & wellControls = getWellControls( subRegion ); - string const wellControlsName = wellControls.getName(); - real64 const & refGravCoef = wellControls.getReferenceGravityCoef(); + string const wellControlsName = getName(); + real64 const & refGravCoef = getReferenceGravityCoef(); real64 & currentBHP = - wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentBHPString() ); + getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentBHPString() ); arrayView1d< real64 > const & dCurrentBHP = - wellControls.getReference< array1d< real64 > >( SinglePhaseWell::viewKeyStruct::dCurrentBHPString() ); + getReference< array1d< real64 > >( SinglePhaseWell::viewKeyStruct::dCurrentBHPString() ); geos::internal::kernelLaunchSelectorThermalSwitch( isThermal(), [&] ( auto ISTHERMAL ) { @@ -303,14 +285,13 @@ void SinglePhaseWell::calculateReferenceElementRates( WellElementSubRegion & sub // control data - WellControls & wellControls = getWellControls( subRegion ); // fluid data - constitutive::SingleFluidBase & fluidSeparator = wellControls.getSingleFluidSeparator(); + constitutive::SingleFluidBase & fluidSeparator = getSingleFluidSeparator(); arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > const & dens = fluidSeparator.density(); real64 & currentVolRate = - wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentVolRateString() ); + getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentVolRateString() ); // bring everything back to host, capture the scalars by reference forAll< serialPolicy >( 1, [connRate, @@ -359,41 +340,41 @@ void SinglePhaseWell::updateSeparator( ElementRegionManager const & elemManager, subRegion.getField< well::pressure >(); // control data - WellControls & wellControls = getWellControls( subRegion ); - string const wellControlsName = wellControls.getName(); - bool const logSurfaceCondition = isLogLevelActive< logInfo::WellControl >( wellControls.getLogLevel()); - integer const useSurfaceConditions = wellControls.useSurfaceConditions(); + + string const wellControlsName = getName(); + bool const logSurfaceCondition = isLogLevelActive< logInfo::WellControl >( getLogLevel()); + integer const useSurfaceCond = useSurfaceConditions(); // fluid data - constitutive::SingleFluidBase & fluidSeparator = wellControls.getSingleFluidSeparator(); + constitutive::SingleFluidBase & fluidSeparator = getSingleFluidSeparator(); arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > const & dens = fluidSeparator.density(); real64 flashPressure; - if( useSurfaceConditions ) + if( useSurfaceCond ) { // use surface conditions - flashPressure = wellControls.getSurfacePressure(); + flashPressure = getSurfacePressure(); } else { - if( !wellControls.referenceReservoirRegion().empty() ) + if( !getReferenceReservoirRegion().empty() ) { - ElementRegionBase const & region = elemManager.getRegion( wellControls.referenceReservoirRegion()); + ElementRegionBase const & region = elemManager.getRegion( getReferenceReservoirRegion()); GEOS_ERROR_IF ( !region.hasWrapper( SinglePhaseStatistics::regionStatisticsName() ), GEOS_FMT( "{}: WellControl {} referenceReservoirRegion field requires SinglePhaseStatistics to be configured for region {} ", - getDataContext(), wellControls.getName(), wellControls.referenceReservoirRegion() ) ); + getDataContext(), getName(), getReferenceReservoirRegion() ) ); SinglePhaseStatistics::RegionStatistics const & stats = region.getReference< SinglePhaseStatistics::RegionStatistics >( SinglePhaseStatistics::regionStatisticsName() ); - wellControls.setRegionAveragePressure( stats.averagePressure ); - wellControls.setRegionAverageTemperature( stats.averageTemperature ); + setRegionAveragePressure( stats.averagePressure ); + setRegionAverageTemperature( stats.averageTemperature ); GEOS_ERROR_IF( stats.averagePressure <= 0.0, GEOS_FMT( "{}: No region average quantities computed. WellControl {} referenceReservoirRegion field requires CompositionalMultiphaseStatistics to be configured for region {} ", - getDataContext(), wellControls.getName(), wellControls.referenceReservoirRegion() )); + getDataContext(), getName(), getReferenceReservoirRegion() )); } // use region conditions - flashPressure = wellControls.getRegionAveragePressure(); + flashPressure = getRegionAveragePressure(); if( flashPressure < 0.0 ) { // use segment conditions @@ -414,7 +395,7 @@ void SinglePhaseWell::updateSeparator( ElementRegionManager const & elemManager, pres, dens, logSurfaceCondition, - &useSurfaceConditions, + &useSurfaceCond, &flashPressure, &iwelemRef, &wellControlsName] ( localIndex const ) @@ -423,7 +404,7 @@ void SinglePhaseWell::updateSeparator( ElementRegionManager const & elemManager, // - Surface conditions: using the surface pressure provided by the user // - Reservoir conditions: using the pressure in the top element - if( useSurfaceConditions ) + if( useSurfaceCond ) { // we need to compute the surface density fluidSeparatorWrapper.update( iwelemRef, 0, flashPressure ); @@ -450,8 +431,8 @@ void SinglePhaseWell::updateSeparator( ElementRegionManager const & elemManager, real64 SinglePhaseWell::updateSubRegionState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) { - WellControls & wellControls = getWellControls( subRegion ); - if( wellControls.getWellState()) + + if( getWellState()) { // update volumetric rates for the well constraints @@ -474,7 +455,7 @@ real64 SinglePhaseWell::updateSubRegionState( ElementRegionManager const & elemM void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) { GEOS_UNUSED_VAR( domain ); - WellControls & wellControls = getWellControls( subRegion ); + PerforationData const & perforationData = *subRegion.getPerforationData(); ElementRegionManager const & elemManager = mesh.getElemManager(); // get the info stored on well elements @@ -501,32 +482,32 @@ void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh bool const hasNonZeroRate = MpiWrapper::max< integer >( hasNonZero( connRate )); - if( time_n <= 0.0 || (wellControls.isWellOpen() && !hasNonZeroRate ) ) + if( time_n <= 0.0 || ( isWellOpen() && !hasNonZeroRate ) ) { - wellControls.setWellState( true ); - if( wellControls.getCurrentConstraint() == nullptr ) + setWellState( true ); + if( getCurrentConstraint() == nullptr ) { - if( wellControls.isProducer() ) + if( isProducer() ) { - wellControls.forSubGroups< MinimumBHPConstraint, ProductionConstraint< VolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, - ProductionConstraint< PhaseVolumeRateConstraint > >( [&]( auto & constraint ) + forSubGroups< MinimumBHPConstraint, ProductionConstraint< VolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, + ProductionConstraint< PhaseVolumeRateConstraint > >( [&]( auto & constraint ) { - if( ConstraintTypeId( wellControls.getControl()) == constraint.getControl() ) + if( ConstraintTypeId( getControl()) == constraint.getControl() ) { - wellControls.setCurrentConstraint( &constraint ); - wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old + setCurrentConstraint( &constraint ); + setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old } } ); } else { - wellControls.forSubGroups< MaximumBHPConstraint, InjectionConstraint< VolumeRateConstraint >, InjectionConstraint< MassRateConstraint >, - InjectionConstraint< PhaseVolumeRateConstraint > >( [&]( auto & constraint ) + forSubGroups< MaximumBHPConstraint, InjectionConstraint< VolumeRateConstraint >, InjectionConstraint< MassRateConstraint >, + InjectionConstraint< PhaseVolumeRateConstraint > >( [&]( auto & constraint ) { - if( ConstraintTypeId( wellControls.getControl()) == constraint.getControl() ) + if( ConstraintTypeId( getControl()) == constraint.getControl() ) { - wellControls.setCurrentConstraint( &constraint ); - wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old + setCurrentConstraint( &constraint ); + setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old } } ); } @@ -546,7 +527,7 @@ void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh perforationData.size(), subRegion.size(), perforationData.getNumPerforationsGlobal(), - wellControls, + *this, 0.0, // initialization done at t = 0 resSinglePhaseFlowAccessors.get( flow::pressure{} ), resSinglePhaseFlowAccessors.get( flow::temperature{} ), @@ -570,15 +551,15 @@ void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh // 5) Estimate the well rates RateInitializationKernel::launch( subRegion.size(), - wellControls, + *this, 0.0, // initialization done at t = 0 wellElemDens, connRate ); calculateReferenceElementRates( subRegion ); - WellConstraintBase * constraint = wellControls.getCurrentConstraint(); - constraint->setBHP ( wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentBHPString() )); - constraint->setTotalVolumeRate ( wellControls.getReference< real64 >( + WellConstraintBase * constraint = getCurrentConstraint(); + constraint->setBHP ( getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentBHPString() )); + constraint->setTotalVolumeRate ( getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentVolRateString() )); //constraint->setMassRate( wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentMassRateString() )); // 7) Copy well / fluid dofs to "prop"_n variables @@ -586,39 +567,39 @@ void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh } else if( !hasNonZeroRate ) { - wellControls.setWellState( false ); + setWellState( false ); GEOS_LOG_RANK_0( "tjb shut wells "<< subRegion.getName()); } else { - wellControls.setWellState( true ); + setWellState( true ); // setup for restart - if( wellControls.getCurrentConstraint() == nullptr ) + if( getCurrentConstraint() == nullptr ) { updateSubRegionState( elemManager, subRegion ); - if( wellControls.isProducer() ) + if( isProducer() ) { - wellControls.forSubGroups< MinimumBHPConstraint, ProductionConstraint< VolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, - ProductionConstraint< PhaseVolumeRateConstraint > >( [&]( - auto - & constraint ) + forSubGroups< MinimumBHPConstraint, ProductionConstraint< VolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, + ProductionConstraint< PhaseVolumeRateConstraint > >( [&]( + auto + & constraint ) { - if( ConstraintTypeId( wellControls.getControl()) == constraint.getControl() ) + if( ConstraintTypeId( getControl()) == constraint.getControl() ) { - wellControls.setCurrentConstraint( &constraint ); + setCurrentConstraint( &constraint ); } } ); } else { - wellControls.forSubGroups< MaximumBHPConstraint, InjectionConstraint< VolumeRateConstraint >, InjectionConstraint< MassRateConstraint >, InjectionConstraint< PhaseVolumeRateConstraint > >( [&]( - auto - & - constraint ) + forSubGroups< MaximumBHPConstraint, InjectionConstraint< VolumeRateConstraint >, InjectionConstraint< MassRateConstraint >, InjectionConstraint< PhaseVolumeRateConstraint > >( [&]( + auto + & + constraint ) { - if( ConstraintTypeId( wellControls.getControl()) == constraint.getControl() ) + if( ConstraintTypeId( getControl()) == constraint.getControl() ) { - wellControls.setCurrentConstraint( &constraint ); + setCurrentConstraint( &constraint ); } } ); } @@ -627,103 +608,67 @@ void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh } } -void SinglePhaseWell::initializeWells( DomainPartition & domain, real64 const & time_n ) -{ - GEOS_MARK_FUNCTION; - GEOS_UNUSED_VAR( time_n ); - - // loop over the wells - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - ElementRegionManager & elemManager = mesh.getElemManager(); - - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - initializeWell( domain, mesh, subRegion, time_n ); - } ); - } ); -} -void SinglePhaseWell::shutDownWell( real64 const time_n, - DomainPartition const & domain, +void SinglePhaseWell::shutDownWell( WellElementSubRegion & subRegion, DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { GEOS_MARK_FUNCTION; - GEOS_UNUSED_VAR( time_n ); string const wellDofKey = dofManager.getKey( wellElementDofName() ); - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel const & mesh, - string_array const & regionNames ) - { - - ElementRegionManager const & elemManager = mesh.getElemManager(); - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion const & subRegion ) - { - // if the well is open, we don't have to do anything, so we just return - WellControls const & wellControls = getWellControls( subRegion ); - if( wellControls.isWellOpen( ) ) - { - return; - } + if( isWellOpen( ) ) + { + return; + } - globalIndex const rankOffset = dofManager.rankOffset(); + globalIndex const rankOffset = dofManager.rankOffset(); - arrayView1d< integer const > const ghostRank = - subRegion.getReference< array1d< integer > >( ObjectManagerBase::viewKeyStruct::ghostRankString() ); - arrayView1d< globalIndex const > const dofNumber = - subRegion.getReference< array1d< globalIndex > >( wellDofKey ); + arrayView1d< integer const > const ghostRank = + subRegion.getReference< array1d< integer > >( ObjectManagerBase::viewKeyStruct::ghostRankString() ); + arrayView1d< globalIndex const > const dofNumber = + subRegion.getReference< array1d< globalIndex > >( wellDofKey ); - arrayView1d< real64 const > const pres = - subRegion.getField< fields::well::pressure >(); - arrayView1d< real64 const > const connRate = - subRegion.getField< fields::well::connectionRate >(); + arrayView1d< real64 const > const pres = + subRegion.getField< fields::well::pressure >(); + arrayView1d< real64 const > const connRate = + subRegion.getField< fields::well::connectionRate >(); - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) - { - if( ghostRank[ei] >= 0 ) - { - return; - } + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + if( ghostRank[ei] >= 0 ) + { + return; + } - globalIndex const dofIndex = dofNumber[ei]; - localIndex const localRow = dofIndex - rankOffset; - real64 rhsValue; - - // 4.1. Apply pressure value to the matrix/rhs - FieldSpecificationEqual::SpecifyFieldValue( dofIndex, - rankOffset, - localMatrix, - rhsValue, - pres[ei], // freeze the current pressure value - pres[ei] ); - localRhs[localRow] = rhsValue; - - // 4.2. Apply rate value to the matrix/rhs - FieldSpecificationEqual::SpecifyFieldValue( dofIndex + 1, - rankOffset, - localMatrix, - rhsValue, - connRate[ei], // freeze the current pressure value - connRate[ei] ); - localRhs[localRow + 1] = rhsValue; + globalIndex const dofIndex = dofNumber[ei]; + localIndex const localRow = dofIndex - rankOffset; + real64 rhsValue; + + // 4.1. Apply pressure value to the matrix/rhs + FieldSpecificationEqual::SpecifyFieldValue( dofIndex, + rankOffset, + localMatrix, + rhsValue, + pres[ei], // freeze the current pressure value + pres[ei] ); + localRhs[localRow] = rhsValue; + + // 4.2. Apply rate value to the matrix/rhs + FieldSpecificationEqual::SpecifyFieldValue( dofIndex + 1, + rankOffset, + localMatrix, + rhsValue, + connRate[ei], // freeze the current pressure value + connRate[ei] ); + localRhs[localRow + 1] = rhsValue; - } ); - } ); } ); -} +} real64 SinglePhaseWell::updateWellState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) { GEOS_MARK_FUNCTION; @@ -731,27 +676,7 @@ real64 SinglePhaseWell::updateWellState( ElementRegionManager const & elemManage updateSubRegionState( elemManager, subRegion ); return 0.0; } -void SinglePhaseWell::updateState( DomainPartition & domain ) -{ - GEOS_MARK_FUNCTION; - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - ElementRegionManager & elemManager = mesh.getElemManager(); - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - WellControls & wellControls = getWellControls( subRegion ); - if( wellControls.getWellState()) - { - updateWellState( elemManager, subRegion ); - } - } ); - } ); - -} +#if 0 void SinglePhaseWell::assembleSystem( real64 const time, real64 const dt, DomainPartition & domain, @@ -775,7 +700,7 @@ void SinglePhaseWell::assembleSystem( real64 const time, assembleAccumulationTerms( time, dt, domain, dofManager, localMatrix, localRhs ); // then assemble the pressure relations between well elements - assemblePressureRelations( time, dt, domain, dofManager, localMatrix, localRhs ); + //assemblePressureRelations( time, dt, domain, dofManager, localMatrix, localRhs ); { forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, @@ -804,6 +729,7 @@ void SinglePhaseWell::assembleSystem( real64 const time, // then apply a special treatment to the wells that are shut shutDownWell( time, domain, dofManager, localMatrix, localRhs ); } +#endif void SinglePhaseWell::assembleWellFluxTerms( real64 const & time, real64 const & dt, @@ -814,7 +740,7 @@ void SinglePhaseWell::assembleWellFluxTerms( real64 const & time, { GEOS_MARK_FUNCTION; GEOS_UNUSED_VAR( time ); - WellControls const & wellControls = getWellControls( subRegion ); + // get a reference to the degree-of-freedom numbers string const wellDofKey = dofManager.getKey( wellElementDofName() ); @@ -827,7 +753,7 @@ void SinglePhaseWell::assembleWellFluxTerms( real64 const & time, createAndLaunch< parallelDevicePolicy<> >( dt, dofManager.rankOffset(), wellDofKey, - wellControls, + *this, subRegion, fluid, localMatrix, @@ -840,40 +766,13 @@ void SinglePhaseWell::assembleWellFluxTerms( real64 const & time, createAndLaunch< parallelDevicePolicy<> >( dt, dofManager.rankOffset(), wellDofKey, - wellControls, + *this, subRegion, localMatrix, localRhs ); } } -void SinglePhaseWell::assembleFluxTerms( real64 const & time_n, - real64 const & dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) -{ - GEOS_MARK_FUNCTION; - - // loop over the wells - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel const & mesh, - string_array const & regionNames ) - { - - ElementRegionManager const & elemManager = mesh.getElemManager(); - - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion const & subRegion ) - { - - assembleWellFluxTerms( time_n, dt, subRegion, dofManager, localMatrix, localRhs ); - } ); - - } ); -} void SinglePhaseWell::assembleWellConstraintTerms( real64 const & time_n, @@ -887,21 +786,21 @@ void SinglePhaseWell::assembleWellConstraintTerms( real64 const & time_n, // the rank that owns the reference well element is responsible for the calculations below. - WellControls & wellControls = getWellControls( subRegion ); - if( !subRegion.isLocallyOwned() || !( wellControls.getWellStatus() == WellControls::Status::OPEN )) + + if( !subRegion.isLocallyOwned() || !( getWellStatus() == WellControls::Status::OPEN )) { return; } { // tjb wellControls.forSubGroups< BHPConstraint, MassConstraint, VolumeRateConstraint >( [&]( auto & constraint ) - wellControls.forSubGroups< BHPConstraint, InjectionConstraint< VolumeRateConstraint >, ProductionConstraint< VolumeRateConstraint > >( [&]( auto & constraint ) + forSubGroups< BHPConstraint, InjectionConstraint< VolumeRateConstraint >, ProductionConstraint< VolumeRateConstraint > >( [&]( auto & constraint ) { - if( constraint.getName() == wellControls.getCurrentConstraint()->getName()) + if( constraint.getName() == getCurrentConstraint()->getName()) { // found limiting constraint // fluid data - constitutive::SingleFluidBase & fluidSeparator = wellControls.getSingleFluidSeparator(); + constitutive::SingleFluidBase & fluidSeparator = getSingleFluidSeparator(); integer isThermal = fluidSeparator.isThermal(); geos::internal::kernelLaunchSelectorThermalSwitch( isThermal, [&] ( auto ISTHERMAL ) @@ -909,7 +808,7 @@ void SinglePhaseWell::assembleWellConstraintTerms( real64 const & time_n, integer constexpr IS_THERMAL = ISTHERMAL(); singlePhaseWellConstraintKernels::ConstraintHelper< IS_THERMAL >::assembleConstraintEquation( time_n, - wellControls, + *this, constraint, subRegion, dofManager.getKey( wellElementDofName() ), @@ -966,32 +865,7 @@ void SinglePhaseWell::assembleWellPressureRelations( real64 const & GEOS_UNUSED_ } ); } -void SinglePhaseWell::assemblePressureRelations( real64 const & time_n, - real64 const & dt, - DomainPartition const & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) -{ - GEOS_MARK_FUNCTION; - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel const & mesh, - string_array const & regionNames ) - { - ElementRegionManager const & elemManager = mesh.getElemManager(); - - - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion const & subRegion ) - { - - assembleWellPressureRelations( time_n, dt, subRegion, dofManager, localMatrix, localRhs ); - } ); - } ); -} void SinglePhaseWell::assembleWellAccumulationTerms( real64 const & time, real64 const & dt, WellElementSubRegion & subRegion, @@ -1005,7 +879,7 @@ void SinglePhaseWell::assembleWellAccumulationTerms( real64 const & time, // get a reference to the degree-of-freedom numbers string const wellElemDofKey = dofManager.getKey( wellElementDofName() ); - WellControls const & wellControls = getWellControls( subRegion ); + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); SingleFluidBase const & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); @@ -1013,7 +887,7 @@ void SinglePhaseWell::assembleWellAccumulationTerms( real64 const & time, { thermalSinglePhaseWellKernels:: ElementBasedAssemblyKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( wellControls.isProducer(), + createAndLaunch< parallelDevicePolicy<> >( isProducer(), dofManager.rankOffset(), wellElemDofKey, subRegion, @@ -1036,119 +910,83 @@ void SinglePhaseWell::assembleWellAccumulationTerms( real64 const & time, -void SinglePhaseWell::assembleAccumulationTerms( real64 const & time_n, - real64 const & dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) +void SinglePhaseWell::computeWellPerforationRates( real64 const & time_n, + real64 const & GEOS_UNUSED_PARAM( dt ), + ElementRegionManager const & elemManager, + WellElementSubRegion & subRegion ) { GEOS_MARK_FUNCTION; + GEOS_UNUSED_VAR( time_n ); + // get the well data + PerforationData * const perforationData = subRegion.getPerforationData(); - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) + if( isWellOpen() && !m_keepVariablesConstantDuringInitStep ) { - ElementRegionManager & elemManager = mesh.getElemManager(); + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + SingleFluidBase const & fluid = getConstitutiveModel< SingleFluidBase >( subRegion, fluidName ); - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion & subRegion ) + if( isThermal() ) { - assembleWellAccumulationTerms( time_n, dt, subRegion, dofManager, localMatrix, localRhs ); - } ); - } ); - + thermalSinglePhasePerforationFluxKernels:: + PerforationFluxKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( getFlowSolverName(), + perforationData, + subRegion, + fluid, + elemManager ); + } + else + { + isothermalSinglePhasePerforationFluxKernels:: + PerforationFluxKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( getFlowSolverName(), + perforationData, + subRegion, + fluid, + elemManager ); + } + } + else + { + // Zero completion flow rate + arrayView1d< real64 > const perfRate = perforationData->getField< fields::well::perforationRate >(); + for( integer iperf=0; iperfsize(); iperf++ ) + { + perfRate[iperf] = 0.0; + } + } } -void SinglePhaseWell::assembleVolumeBalanceTerms( DomainPartition const & GEOS_UNUSED_PARAM( domain ), - DofManager const & GEOS_UNUSED_PARAM( dofManager ), - CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), - arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) -{ - // not implemented for single phase flow -} -void SinglePhaseWell::computePerforationRates( real64 const & time_n, - real64 const & dt, DomainPartition & domain ) +real64 +SinglePhaseWell::scalingForWellSystemSolution( WellElementSubRegion & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution ) { GEOS_MARK_FUNCTION; - GEOS_UNUSED_VAR( time_n ); - GEOS_UNUSED_VAR( dt ); - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - - // TODO: change the way we access the flowSolver here - SinglePhaseBase const & flowSolver = getParent().getGroup< SinglePhaseBase >( getFlowSolverName() ); - PerforationKernel::SinglePhaseFlowAccessors resSinglePhaseFlowAccessors( mesh.getElemManager(), flowSolver.getName() ); - PerforationKernel::SingleFluidAccessors resSingleFluidAccessors( mesh.getElemManager(), flowSolver.getName() ); - ElementRegionManager & elemManager = mesh.getElemManager(); - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - - // get the well data - PerforationData * const perforationData = subRegion.getPerforationData(); - WellControls const & wellControls = getWellControls( subRegion ); - if( wellControls.isWellOpen() && !m_keepVariablesConstantDuringInitStep ) - { - - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - SingleFluidBase const & fluid = getConstitutiveModel< SingleFluidBase >( subRegion, fluidName ); + GEOS_UNUSED_VAR( subRegion ); + GEOS_UNUSED_VAR( dofManager ); + GEOS_UNUSED_VAR( localSolution ); - if( isThermal() ) - { - thermalSinglePhasePerforationFluxKernels:: - PerforationFluxKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( flowSolver.getName(), - perforationData, - subRegion, - fluid, - elemManager ); - } - else - { - isothermalSinglePhasePerforationFluxKernels:: - PerforationFluxKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( flowSolver.getName(), - perforationData, - subRegion, - fluid, - elemManager ); - } - } - else - { - // Zero completion flow rate - arrayView1d< real64 > const perfRate = perforationData->getField< fields::well::perforationRate >(); - for( integer iperf=0; iperfsize(); iperf++ ) - { - perfRate[iperf] = 0.0; - } - } - } ); - } ); + return 1.0; } - - -real64 -SinglePhaseWell::calculateWellResidualNorm( real64 const & time_n, - real64 const & dt, - WellElementSubRegion const & subRegion, - DofManager const & dofManager, - arrayView1d< real64 const > const & localRhs ) +array1d< real64 > +SinglePhaseWell::calculateLocalWellResidualNorm( real64 const & time_n, + real64 const & dt, + NonlinearSolverParameters const & nonlinearSolverParameters, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs ) { GEOS_MARK_FUNCTION; - integer numNorm = 1; // mass balance + integer numNorm = 1; // mass balance array1d< real64 > localResidualNorm; array1d< real64 > localResidualNormalizer; if( isThermal() ) { - numNorm = 2; // mass balance and energy balance + numNorm = 2; // mass balance and energy balance } localResidualNorm.resize( numNorm ); localResidualNormalizer.resize( numNorm ); @@ -1162,110 +1000,79 @@ SinglePhaseWell::calculateWellResidualNorm( real64 const & time_n, string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); SingleFluidBase const & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); - WellControls const & wellControls = getWellControls( subRegion ); - // step 1: compute the norm in the subRegion - if( isThermal() ) + + if( isWellOpen() ) { - real64 subRegionResidualNorm[2]{}; - thermalSinglePhaseWellKernels::ResidualNormKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( rankOffset, - wellDofKey, - localRhs, - subRegion, - fluid, - wellControls, - time_n, - dt, - m_nonlinearSolverParameters.m_minNormalizer, - subRegionResidualNorm ); - // step 2: reduction across meshBodies/regions/subRegions - - for( integer i=0; i localResidualNorm[i] ) + real64 subRegionResidualNorm[2]{}; + thermalSinglePhaseWellKernels::ResidualNormKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( rankOffset, + wellDofKey, + localRhs, + subRegion, + fluid, + *this, + time_n, + dt, + nonlinearSolverParameters.m_minNormalizer, + subRegionResidualNorm ); + // step 2: reduction across meshBodies/regions/subRegions + + for( integer i=0; i localResidualNorm[i] ) + { + localResidualNorm[i] = subRegionResidualNorm[i]; + } } } - } - else - { - real64 subRegionResidualNorm[1]{}; - ResidualNormKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( rankOffset, - wellDofKey, - localRhs, - subRegion, - fluid, - wellControls, - time_n, - dt, - m_nonlinearSolverParameters.m_minNormalizer, - subRegionResidualNorm ); - - // step 2: reduction across meshBodies/regions/subRegions - - if( subRegionResidualNorm[0] > localResidualNorm[0] ) + else { - localResidualNorm[0] = subRegionResidualNorm[0]; + real64 subRegionResidualNorm[1]{}; + ResidualNormKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( rankOffset, + wellDofKey, + localRhs, + subRegion, + fluid, + *this, + time_n, + dt, + nonlinearSolverParameters.m_minNormalizer, + subRegionResidualNorm ); + + // step 2: reduction across meshBodies/regions/subRegions + + if( subRegionResidualNorm[0] > localResidualNorm[0] ) + { + localResidualNorm[0] = subRegionResidualNorm[0]; + } } } + return localResidualNorm; - real64 resNorm=localResidualNorm[0]; - if( isThermal() ) - { - real64 globalResidualNorm[2]{}; - globalResidualNorm[0] = MpiWrapper::max( localResidualNorm[0] ); - globalResidualNorm[1] = MpiWrapper::max( localResidualNorm[1] ); - resNorm= std::sqrt( globalResidualNorm[0] * globalResidualNorm[0] + globalResidualNorm[1] * globalResidualNorm[1] ); - - GEOS_LOG_LEVEL_RANK_0_NLR( logInfo::ResidualNorm, GEOS_FMT( " ( R{} ) = ( {:4.2e} ) ( Renergy ) = ( {:4.2e} )", - coupledSolverAttributePrefix(), globalResidualNorm[0], globalResidualNorm[1] )); - - getConvergenceStats().setResidualValue( GEOS_FMT( "R{}", coupledSolverAttributePrefix()), globalResidualNorm[0] ); - getConvergenceStats().setResidualValue( "Renergy", globalResidualNorm[1] ); - } - else - { - resNorm = MpiWrapper::max( resNorm ); - - GEOS_LOG_LEVEL_RANK_0_NLR( logInfo::ResidualNorm, GEOS_FMT( " ( R{} ) = ( {:4.2e} )", - coupledSolverAttributePrefix(), resNorm )); - getConvergenceStats().setResidualValue( GEOS_FMT( "R{}", coupledSolverAttributePrefix()), resNorm ); - } - - return resNorm; -} -real64 -SinglePhaseWell::scalingForWellSystemSolution( ElementSubRegionBase & subRegion, - DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution ) -{ - GEOS_MARK_FUNCTION; - GEOS_UNUSED_VAR( subRegion ); - GEOS_UNUSED_VAR( dofManager ); - GEOS_UNUSED_VAR( localSolution ); - - return 1.0; } real64 -SinglePhaseWell::calculateResidualNorm( real64 const & time_n, - real64 const & dt, - DomainPartition const & domain, - DofManager const & dofManager, - arrayView1d< real64 const > const & localRhs ) +SinglePhaseWell::calculateWellResidualNorm( real64 const & time_n, + real64 const & dt, + NonlinearSolverParameters const & nonlinearSolverParameters, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs ) { GEOS_MARK_FUNCTION; - integer numNorm = 1; // mass balance + integer numNorm = 1; // mass balance array1d< real64 > localResidualNorm; array1d< real64 > localResidualNormalizer; if( isThermal() ) { - numNorm = 2; // mass balance and energy balance + numNorm = 2; // mass balance and energy balance } localResidualNorm.resize( numNorm ); localResidualNormalizer.resize( numNorm ); @@ -1274,77 +1081,15 @@ SinglePhaseWell::calculateResidualNorm( real64 const & time_n, globalIndex const rankOffset = dofManager.rankOffset(); string const wellDofKey = dofManager.getKey( wellElementDofName() ); - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel const & mesh, - string_array const & regionNames ) + if( isWellOpen() ) { - - ElementRegionManager const & elemManager = mesh.getElemManager(); - - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion const & subRegion ) - { - - - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - SingleFluidBase const & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); - - WellControls const & wellControls = getWellControls( subRegion ); - - if( wellControls.isWellOpen() ) - { - // step 1: compute the norm in the subRegion - if( isThermal() ) - { - real64 subRegionResidualNorm[2]{}; - thermalSinglePhaseWellKernels::ResidualNormKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( rankOffset, - wellDofKey, - localRhs, - subRegion, - fluid, - wellControls, - time_n, - dt, - m_nonlinearSolverParameters.m_minNormalizer, - subRegionResidualNorm ); - // step 2: reduction across meshBodies/regions/subRegions - - for( integer i=0; i localResidualNorm[i] ) - { - localResidualNorm[i] = subRegionResidualNorm[i]; - } - } - } - else - { - real64 subRegionResidualNorm[1]{}; - ResidualNormKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( rankOffset, - wellDofKey, - localRhs, - subRegion, - fluid, - wellControls, - time_n, - dt, - m_nonlinearSolverParameters.m_minNormalizer, - subRegionResidualNorm ); - - // step 2: reduction across meshBodies/regions/subRegions - - if( subRegionResidualNorm[0] > localResidualNorm[0] ) - { - localResidualNorm[0] = subRegionResidualNorm[0]; - } - } - } - } ); - } ); - + localResidualNorm = calculateLocalWellResidualNorm( time_n, + dt, + nonlinearSolverParameters, + subRegion, + dofManager, + localRhs ); + } real64 resNorm=localResidualNorm[0]; if( isThermal() ) { @@ -1356,8 +1101,8 @@ SinglePhaseWell::calculateResidualNorm( real64 const & time_n, GEOS_LOG_LEVEL_RANK_0_NLR( logInfo::ResidualNorm, GEOS_FMT( " ( R{} ) = ( {:4.2e} ) ( Renergy ) = ( {:4.2e} )", coupledSolverAttributePrefix(), globalResidualNorm[0], globalResidualNorm[1] )); - getConvergenceStats().setResidualValue( GEOS_FMT( "R{}", coupledSolverAttributePrefix()), globalResidualNorm[0] ); - getConvergenceStats().setResidualValue( "Renergy", globalResidualNorm[1] ); + //getConvergenceStats().setResidualValue( GEOS_FMT( "R{}", coupledSolverAttributePrefix()), globalResidualNorm[0] ); + //getConvergenceStats().setResidualValue( "Renergy", globalResidualNorm[1] ); } else { @@ -1365,12 +1110,12 @@ SinglePhaseWell::calculateResidualNorm( real64 const & time_n, GEOS_LOG_LEVEL_RANK_0_NLR( logInfo::ResidualNorm, GEOS_FMT( " ( R{} ) = ( {:4.2e} )", coupledSolverAttributePrefix(), resNorm )); - getConvergenceStats().setResidualValue( GEOS_FMT( "R{}", coupledSolverAttributePrefix()), resNorm ); + //getConvergenceStats().setResidualValue( GEOS_FMT( "R{}", coupledSolverAttributePrefix()), resNorm ); } return resNorm; } -bool SinglePhaseWell::checkWellSystemSolution( ElementSubRegionBase & subRegion, +bool SinglePhaseWell::checkWellSystemSolution( WellElementSubRegion & subRegion, DofManager const & dofManager, arrayView1d< real64 const > const & localSolution, real64 const scalingFactor ) @@ -1412,59 +1157,7 @@ bool SinglePhaseWell::checkWellSystemSolution( ElementSubRegionBase & subRegion, return (m_allowNegativePressure || numNegativePressures == 0) ? 1 : 0; } -bool SinglePhaseWell::checkSystemSolution( DomainPartition & domain, - DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution, - real64 const scalingFactor ) -{ - GEOS_MARK_FUNCTION; - string const wellDofKey = dofManager.getKey( wellElementDofName() ); - integer numNegativePressures = 0; - real64 minPressure = 0.0; - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel const & mesh, - string_array const & regionNames ) - { - - ElementRegionManager const & elemManager = mesh.getElemManager(); - - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion const & subRegion ) - - { - globalIndex const rankOffset = dofManager.rankOffset(); - // get the degree of freedom numbers on well elements - arrayView1d< globalIndex const > const & dofNumber = - subRegion.getReference< array1d< globalIndex > >( wellDofKey ); - arrayView1d< integer const > const & ghostRank = subRegion.ghostRank(); - - // get a reference to the primary variables on well elements - arrayView1d< real64 const > const & pres = - subRegion.getField< well::pressure >(); - - std::pair< integer, real64 > statistics = - singlePhaseBaseKernels::SolutionCheckKernel:: - launch< parallelDevicePolicy<> >( localSolution, rankOffset, dofNumber, ghostRank, pres, scalingFactor ); - - numNegativePressures += statistics.first; - minPressure = std::min( minPressure, statistics.second ); - } ); - } ); - - numNegativePressures = MpiWrapper::sum( numNegativePressures ); - - if( numNegativePressures > 0 ) - { - GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, - GEOS_FMT( " {}: Number of negative pressure values: {}, minimum value: {} Pa", - getName(), numNegativePressures, fmt::format( "{:.{}f}", minPressure, 3 ) ) ); - } - - return (m_allowNegativePressure || numNegativePressures == 0) ? 1 : 0; -} void SinglePhaseWell::applyWellSystemSolution( DofManager const & dofManager, @@ -1526,103 +1219,34 @@ SinglePhaseWell::applyWellSystemSolution( DofManager const & dofManager, } -void -SinglePhaseWell::applySystemSolution( DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution, - real64 const scalingFactor, - real64 const dt, - DomainPartition & domain ) + +void SinglePhaseWell::resetStateToBeginningOfStep( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) { - GEOS_UNUSED_VAR( dt ); - DofManager::CompMask pressureMask( m_numDofPerWellElement, 0, 1 ); - DofManager::CompMask connRateMask( m_numDofPerWellElement, 1, 2 ); - dofManager.addVectorToField( localSolution, - wellElementDofName(), - well::pressure::key(), - scalingFactor, - pressureMask ); - dofManager.addVectorToField( localSolution, - wellElementDofName(), - well::connectionRate::key(), - scalingFactor, - connRateMask ); + + // get a reference to the primary variables on well elements + arrayView1d< real64 > const & wellElemPressure = + subRegion.getField< well::pressure >(); + arrayView1d< real64 const > const & wellElemPressure_n = + subRegion.getField< well::pressure_n >(); + wellElemPressure.setValues< parallelDevicePolicy<> >( wellElemPressure_n ); if( isThermal() ) { - DofManager::CompMask temperatureMask( m_numDofPerWellElement, 2, 3 ); - - dofManager.addVectorToField( localSolution, - wellElementDofName(), - fields::well::temperature::key(), - scalingFactor, - temperatureMask ); - + arrayView1d< real64 > const & wellElemTemperature = + subRegion.getField< fields::well::temperature >(); + arrayView1d< real64 const > const & wellElemTemperature_n = + subRegion.getField< fields::well::temperature_n >(); + wellElemTemperature.setValues< parallelDevicePolicy<> >( wellElemTemperature_n ); } + arrayView1d< real64 > const & connRate = + subRegion.getField< well::connectionRate >(); + arrayView1d< real64 const > const & connRate_n = + subRegion.getField< well::connectionRate_n >(); + connRate.setValues< parallelDevicePolicy<> >( connRate_n ); - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - FieldIdentifiers fieldsToBeSync; - if( isThermal() ) - { - fieldsToBeSync.addElementFields( { well::pressure::key(), - well::connectionRate::key(), - well::temperature::key() }, - regionNames ); - } - else - { - fieldsToBeSync.addElementFields( { well::pressure::key(), - well::connectionRate::key() }, - regionNames ); - } - CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, - mesh, - domain.getNeighbors(), - true ); - } ); - -} - -void SinglePhaseWell::resetStateToBeginningOfStep( DomainPartition & domain ) -{ - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - ElementRegionManager & elemManager = mesh.getElemManager(); - - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - // get a reference to the primary variables on well elements - arrayView1d< real64 > const & wellElemPressure = - subRegion.getField< well::pressure >(); - arrayView1d< real64 const > const & wellElemPressure_n = - subRegion.getField< well::pressure_n >(); - wellElemPressure.setValues< parallelDevicePolicy<> >( wellElemPressure_n ); - - if( isThermal() ) - { - arrayView1d< real64 > const & wellElemTemperature = - subRegion.getField< fields::well::temperature >(); - arrayView1d< real64 const > const & wellElemTemperature_n = - subRegion.getField< fields::well::temperature_n >(); - wellElemTemperature.setValues< parallelDevicePolicy<> >( wellElemTemperature_n ); - } - arrayView1d< real64 > const & connRate = - subRegion.getField< well::connectionRate >(); - arrayView1d< real64 const > const & connRate_n = - subRegion.getField< well::connectionRate_n >(); - connRate.setValues< parallelDevicePolicy<> >( connRate_n ); + updateSubRegionState( elemManager, subRegion ); - updateSubRegionState( elemManager, subRegion ); - } ); - } ); } void SinglePhaseWell::saveState( WellElementSubRegion & subRegion ) @@ -1646,176 +1270,154 @@ void SinglePhaseWell::saveState( WellElementSubRegion & subRegion ) fluid.saveConvergedState(); } -void SinglePhaseWell::implicitStepSetup( real64 const & time, +void SinglePhaseWell::implicitStepSetup( real64 const & time_n, real64 const & dt, - DomainPartition & domain ) + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion ) { - WellSolverBase::implicitStepSetup( time, dt, domain ); + GEOS_MARK_FUNCTION; + WellControls::implicitStepSetup( time_n, dt, elemManager, subRegion ); + arrayView1d< real64 const > const wellElemPressure = subRegion.getField< well::pressure >(); + arrayView1d< real64 > const wellElemPressure_n = subRegion.getField< well::pressure_n >(); + wellElemPressure_n.setValues< parallelDevicePolicy<> >( wellElemPressure ); - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) + if( isThermal() ) { + arrayView1d< real64 const > const wellElemTemperature = subRegion.getField< well::temperature >(); + arrayView1d< real64 > const wellElemTemperature_n = subRegion.getField< well::temperature_n >(); + wellElemTemperature_n.setValues< parallelDevicePolicy<> >( wellElemTemperature ); + } + arrayView1d< real64 const > const connRate = subRegion.getField< well::connectionRate >(); + arrayView1d< real64 > const connRate_n = subRegion.getField< well::connectionRate_n >(); + connRate_n.setValues< parallelDevicePolicy<> >( connRate ); - ElementRegionManager & elemManager = mesh.getElemManager(); - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - arrayView1d< real64 const > const wellElemPressure = subRegion.getField< well::pressure >(); - arrayView1d< real64 > const wellElemPressure_n = subRegion.getField< well::pressure_n >(); - wellElemPressure_n.setValues< parallelDevicePolicy<> >( wellElemPressure ); - - if( isThermal() ) - { - arrayView1d< real64 const > const wellElemTemperature = subRegion.getField< well::temperature >(); - arrayView1d< real64 > const wellElemTemperature_n = subRegion.getField< well::temperature_n >(); - wellElemTemperature_n.setValues< parallelDevicePolicy<> >( wellElemTemperature ); - } - arrayView1d< real64 const > const connRate = subRegion.getField< well::connectionRate >(); - arrayView1d< real64 > const connRate_n = subRegion.getField< well::connectionRate_n >(); - connRate_n.setValues< parallelDevicePolicy<> >( connRate ); + SingleFluidBase const & fluid = + getConstitutiveModel< SingleFluidBase >( subRegion, subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ) ); + fluid.saveConvergedState(); - SingleFluidBase const & fluid = - getConstitutiveModel< SingleFluidBase >( subRegion, subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ) ); - fluid.saveConvergedState(); + validateWellConstraints( time_n, dt, subRegion ); - validateWellConstraints( time, dt, subRegion ); + updateSubRegionState( elemManager, subRegion ); - updateSubRegionState( elemManager, subRegion ); - } ); - } ); } void SinglePhaseWell::implicitStepComplete( real64 const & time_n, real64 const & dt, - DomainPartition & domain ) + WellElementSubRegion const & subRegion ) { - WellSolverBase::implicitStepComplete( time_n, dt, domain ); +// WellSolverBase::implicitStepComplete( time_n, dt, domain ); if( getLogLevel() > 0 ) { - printRates( time_n, dt, domain ); + printRates( time_n, dt, subRegion ); } } void SinglePhaseWell::printRates( real64 const & time_n, - real64 const & GEOS_UNUSED_PARAM( dt ), - DomainPartition & domain ) + real64 const & dt, + WellElementSubRegion const & subRegion ) { - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - ElementRegionManager & elemManager = mesh.getElemManager(); - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion & subRegion ) - { + // the rank that owns the reference well element is responsible for the calculations below. + if( !subRegion.isLocallyOwned() ) + { + return; + } - // the rank that owns the reference well element is responsible for the calculations below. - if( !subRegion.isLocallyOwned() ) - { - return; - } + localIndex const iwelemRef = subRegion.getTopWellElementIndex(); - localIndex const iwelemRef = subRegion.getTopWellElementIndex(); + // subRegion data - // subRegion data + arrayView1d< real64 const > const & connRate = + subRegion.getField< well::connectionRate >(); - arrayView1d< real64 const > const & connRate = - subRegion.getField< well::connectionRate >(); + // control data - // control data - WellControls const & wellControls = getWellControls( subRegion ); - string const wellControlsName = wellControls.getName(); + string const wellControlsName = getName(); - // format: time,total_rate,total_vol_rate - std::ofstream outputFile; - if( m_writeCSV > 0 ) - { - outputFile.open( m_ratesOutputDir + "/" + wellControlsName + ".csv", std::ios_base::app ); - outputFile << time_n; - } + // format: time,total_rate,total_vol_rate + std::ofstream outputFile; + if( m_writeCSV > 0 ) + { + outputFile.open( m_ratesOutputDir + "/" + wellControlsName + ".csv", std::ios_base::app ); + outputFile << time_n; + } - if( !wellControls.isWellOpen() ) - { - GEOS_LOG( GEOS_FMT( "{}: well is shut", wellControlsName ) ); - if( outputFile.is_open()) - { - // print all zeros in the rates file - outputFile << ",0.0,0.0,0.0" << std::endl; - outputFile.close(); - } - return; - } + if( !isWellOpen() ) + { + GEOS_LOG( GEOS_FMT( "{}: well is shut", wellControlsName ) ); + if( outputFile.is_open()) + { + // print all zeros in the rates file + outputFile << ",0.0,0.0,0.0" << std::endl; + outputFile.close(); + } + return; + } - integer const useSurfaceConditions = wellControls.useSurfaceConditions(); + integer const useSurfaceCond = useSurfaceConditions(); - real64 const & currentBHP = - wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentBHPString() ); - real64 const & currentTotalVolRate = - wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentVolRateString() ); + real64 const & currentBHP = + getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentBHPString() ); + real64 const & currentTotalVolRate = + getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentVolRateString() ); - // bring everything back to host, capture the scalars by reference - forAll< serialPolicy >( 1, [&useSurfaceConditions, - ¤tBHP, - connRate, - ¤tTotalVolRate, - &iwelemRef, - &wellControlsName, - &outputFile] ( localIndex const ) - { - string const conditionKey = useSurfaceConditions ? "surface" : "reservoir"; - string const unitKey = useSurfaceConditions ? "s" : "r"; - - real64 const currentTotalRate = connRate[iwelemRef]; - GEOS_LOG( GEOS_FMT( "{}: BHP (at the specified reference elevation): {} Pa", - wellControlsName, currentBHP ) ); - GEOS_LOG( GEOS_FMT( "{}: Total rate: {} kg/s; total {} volumetric rate: {} {}m3/s", - wellControlsName, currentTotalRate, conditionKey, currentTotalVolRate, unitKey ) ); - if( outputFile.is_open()) - { - outputFile << "," << currentBHP; - outputFile << "," << currentTotalRate << "," << currentTotalVolRate << std::endl; - outputFile.close(); - } - } ); - } ); + // bring everything back to host, capture the scalars by reference + forAll< serialPolicy >( 1, [&useSurfaceCond, + ¤tBHP, + connRate, + ¤tTotalVolRate, + &iwelemRef, + &wellControlsName, + &outputFile] ( localIndex const ) + { + string const conditionKey = useSurfaceCond ? "surface" : "reservoir"; + string const unitKey = useSurfaceCond ? "s" : "r"; + + real64 const currentTotalRate = connRate[iwelemRef]; + GEOS_LOG( GEOS_FMT( "{}: BHP (at the specified reference elevation): {} Pa", + wellControlsName, currentBHP ) ); + GEOS_LOG( GEOS_FMT( "{}: Total rate: {} kg/s; total {} volumetric rate: {} {}m3/s", + wellControlsName, currentTotalRate, conditionKey, currentTotalVolRate, unitKey ) ); + if( outputFile.is_open()) + { + outputFile << "," << currentBHP; + outputFile << "," << currentTotalRate << "," << currentTotalVolRate << std::endl; + outputFile.close(); + } } ); } bool SinglePhaseWell::evaluateConstraints( real64 const & time_n, WellElementSubRegion & subRegion ) { - WellControls & wellControls = getWellControls( subRegion ); + // create list of all constraints to process std::vector< WellConstraintBase * > constraintList; - if( wellControls.isProducer() ) + if( isProducer() ) { - constraintList = wellControls.getProdRateConstraints(); + constraintList = getProdRateConstraints(); // Solve minimum bhp constraint first - constraintList.insert( constraintList.begin(), wellControls.getMinBHPConstraint() ); + constraintList.insert( constraintList.begin(), getMinBHPConstraint() ); } else { - constraintList = wellControls.getInjRateConstraints(); + constraintList = getInjRateConstraints(); // Solve maximum bhp constraint first; - constraintList.insert( constraintList.begin(), wellControls.getMaxBHPConstraint() ); + constraintList.insert( constraintList.begin(), getMaxBHPConstraint() ); } // Get current constraint WellConstraintBase * limitingConstraint = nullptr; for( auto & constraint : constraintList ) { - if( constraint->getName() == wellControls.getCurrentConstraint()->getName()) + if( constraint->getName() == getCurrentConstraint()->getName()) { limitingConstraint = constraint; // tjb. this is likely not needed. set in update state - constraint->setBHP ( wellControls.getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentBHPString() )); - constraint->setTotalVolumeRate ( wellControls.getReference< real64 >( + constraint->setBHP ( getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentBHPString() )); + constraint->setTotalVolumeRate ( getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentVolRateString() )); GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), @@ -1835,19 +1437,20 @@ bool SinglePhaseWell::evaluateConstraints( real64 const & time_n, // limitingConstraint->getName() << std::endl; if( constraint->checkViolation( *limitingConstraint, time_n ) ) { - wellControls.setControl( static_cast< WellControls::Control >(constraint->getControl()) ); // tjb old - wellControls.setCurrentConstraint( constraint ); + setControl( static_cast< WellControls::Control >(constraint->getControl()) ); // tjb old + setCurrentConstraint( constraint ); GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), " Well " << subRegion.getName() << " New Limiting Constraint " << constraint->getName() << " " << constraint->getConstraintValue( time_n ) ); } } } GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), - " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << limitingConstraint->phaseVolumeRates() << " " << + " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << + limitingConstraint->phaseVolumeRates() << " " << limitingConstraint->totalVolumeRate() << " " << limitingConstraint->massRate()); return true; } -REGISTER_CATALOG_ENTRY( PhysicsSolverBase, SinglePhaseWell, string const &, Group * const ) + }// namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp index df5408f267b..2fa94d88ac0 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp @@ -20,7 +20,7 @@ #ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_SINGLEPHASEWELL_HPP_ #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_SINGLEPHASEWELL_HPP_ -#include "physicsSolvers/fluidFlow/wells/WellSolverBase.hpp" +#include "physicsSolvers/fluidFlow/wells/WellControls.hpp" #include "constitutive/fluid/singlefluid/SingleFluidLayouts.hpp" @@ -43,7 +43,7 @@ class WellElementSubRegion; * * A single-phase well solver */ -class SinglePhaseWell : public WellSolverBase +class SinglePhaseWell : public WellControls { public: @@ -76,17 +76,80 @@ class SinglePhaseWell : public WellSolverBase */ virtual ~SinglePhaseWell() override = default; + void registerWellDataOnMesh( WellElementSubRegion & subRegion ) override; + + /** + * @defgroup WellManager Interface Functions + * + * These functions provide the primary interface that is required for derived classes + * The "Well" versions apply to individual well subRegions, whereas the others apply to all wells + */ + /**@{*/ + /** + * * @brief Initialize well for the beginning of a simulation or restart + * @param domain the domain + * @param mesh the mesh level + * @param subRegion the well subRegion + * @param time_n the current time + */ + virtual void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n )override; + + virtual void initializeWellPostInitialConditionsPreSubGroups( WellElementSubRegion & subRegion )override; /** - * @brief name of the node manager in the object catalog - * @return string that contains the catalog name to generate a new NodeManager object through the object catalog. + * @brief Function to evaluate well constraints after applying the solution update + * @param time_n the time at the beginning of the time step + * @param subRegion the well subRegion + * @return true if all constraints are satisfied, false otherwise */ - static string catalogName() { return "SinglePhaseWell"; } + virtual bool evaluateConstraints( real64 const & time_n, + WellElementSubRegion & subRegion ) override; + /** + * @copydoc WellControls::assembleWellAccumulationTerms() + */ + virtual void assembleWellAccumulationTerms( real64 const & time, + real64 const & dt, + WellElementSubRegion & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; /** - * @copydoc PhysicsSolverBase::getCatalogName() + * @copydoc WellControls::assembleWellConstraintTerms() */ - string getCatalogName() const override { return catalogName(); } + virtual void assembleWellPressureRelations( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; - virtual void registerDataOnMesh( Group & meshBodies ) override; + /** + * @copydoc WellControls::assembleWellConstraintTerms() + */ + virtual void assembleWellConstraintTerms( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; + + /** + * @copydoc WellControls::computeWellPerforationRates() + */ + virtual void computeWellPerforationRates( real64 const & time_n, + real64 const & GEOS_UNUSED_PARAM( dt ), + ElementRegionManager const & elemManager, + WellElementSubRegion & subRegion ) override; + + /** + * @copydoc WellControls::assembleFluxTerms() + */ + virtual void assembleWellFluxTerms( real64 const & time, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; + /**@}*/ /** * @defgroup Solver Interface Functions @@ -96,49 +159,40 @@ class SinglePhaseWell : public WellSolverBase */ /**@{*/ - virtual real64 - calculateResidualNorm( real64 const & time_n, - real64 const & dt, - DomainPartition const & domain, - DofManager const & dofManager, - arrayView1d< real64 const > const & localRhs ) override; + virtual array1d< real64 > + calculateLocalWellResidualNorm( real64 const & time_n, + real64 const & dt, + NonlinearSolverParameters const & nonlinearSolverParameters, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs )override; + virtual real64 calculateWellResidualNorm( real64 const & time_n, real64 const & dt, + NonlinearSolverParameters const & nonlinearSolverParameters, WellElementSubRegion const & subRegion, DofManager const & dofManager, arrayView1d< real64 const > const & localRhs ) override; - - virtual real64 scalingForWellSystemSolution( ElementSubRegionBase & subRegion, + virtual real64 scalingForWellSystemSolution( WellElementSubRegion & subRegion, DofManager const & dofManager, arrayView1d< real64 const > const & localSolution ) override; /** - * @copydoc PhysicsSolverBase::checkSystemSolution() + * @copydoc WellControls::checkSystemSolution() */ - virtual bool - checkSystemSolution( DomainPartition & domain, - DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution, - real64 const scalingFactor ) override; + virtual bool - checkWellSystemSolution( ElementSubRegionBase & subRegion, + checkWellSystemSolution( WellElementSubRegion & subRegion, DofManager const & dofManager, arrayView1d< real64 const > const & localSolution, real64 const scalingFactor ) override; /** - * @copydoc PhysicsSolverBase::applySystemSolution() + * @copydoc WellControls::applyWellSystemSolution() */ virtual void - applySystemSolution( DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution, - real64 const scalingFactor, - real64 const dt, - DomainPartition & domain ) override; - - virtual void applyWellSystemSolution( DofManager const & dofManager, arrayView1d< real64 const > const & localSolution, real64 const scalingFactor, @@ -147,18 +201,22 @@ class SinglePhaseWell : public WellSolverBase MeshLevel & mesh, WellElementSubRegion & subRegion ) override; - virtual void - resetStateToBeginningOfStep( DomainPartition & domain ) override; - virtual void - implicitStepSetup( real64 const & time, - real64 const & dt, - DomainPartition & domain ) override; + virtual void resetStateToBeginningOfStep( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) override; + + virtual void implicitStepSetup( real64 const & time_n, + real64 const & GEOS_UNUSED_PARAM( dt ), + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion )override; virtual void implicitStepComplete( real64 const & time, real64 const & dt, - DomainPartition & domain ) override; + WellElementSubRegion const & subRegion ) override; + + virtual void printRates( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion ) override; /**@}*/ @@ -195,13 +253,6 @@ class SinglePhaseWell : public WellSolverBase */ void updateSeparator( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ); - /** - * @brief Recompute the perforation rates for all the wells - * @param domain the domain containing the mesh and fields - */ - virtual void computePerforationRates( real64 const & time_n, - real64 const & dt, DomainPartition & domain ) override; - /** * @brief Recompute all dependent quantities from primary variables (including constitutive * models) @@ -210,7 +261,7 @@ class SinglePhaseWell : public WellSolverBase * @param subRegion the well subRegion containing the well elements and their associated */ virtual real64 updateWellState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) override; - virtual void updateState( DomainPartition & domain ) override; + /** * @brief Recompute all dependent quantities from primary variables (including constitutive models) @@ -219,142 +270,18 @@ class SinglePhaseWell : public WellSolverBase */ virtual real64 updateSubRegionState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) override; - /** - * @brief function to assemble the linear system matrix and rhs - * @param time the time at the beginning of the step - * @param dt the desired timestep - * @param domain the domain partition - * @param dofManager degree-of-freedom manager associated with the linear system - * @param matrix the system matrix - * @param rhs the system right-hand side vector - */ - virtual void assembleSystem( real64 const time, - real64 const dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) override; - - /** - * @brief assembles the flux terms for all connections between well elements - * @param time_n previous time value - * @param dt time step - * @param domain the physical domain object - * @param dofManager degree-of-freedom manager associated with the linear system - * @param matrix the system matrix - * @param rhs the system right-hand side vector - */ - virtual void assembleWellFluxTerms( real64 const & time, - real64 const & dt, - WellElementSubRegion const & subRegion, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) override; - /** - * @brief assembles the flux terms for all connections between well elements - * @param time_n previous time value - * @param dt time step - * @param domain the physical domain object - * @param dofManager degree-of-freedom manager associated with the linear system - * @param matrix the system matrix - * @param rhs the system right-hand side vector - */ - virtual void assembleFluxTerms( real64 const & time_n, - real64 const & dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) override; - - /** - * @brief assembles the accumulation term for all the well elements - * @param domain the physical domain object - * @param dofManager degree-of-freedom manager associated with the linear system - * @param matrix the system matrix - * @param rhs the system right-hand side vector - */ - - virtual void assembleWellAccumulationTerms( real64 const & time, - real64 const & dt, - WellElementSubRegion & subRegion, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) override; - - virtual void assembleAccumulationTerms( real64 const & time_n, - real64 const & dt, DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) override; - - /** - * @copydoc WellSolverBase::assembleWellConstraintTerms() - */ - virtual void assembleWellConstraintTerms( real64 const & time_n, - real64 const & dt, - WellElementSubRegion const & subRegion, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) override; - - - virtual void assembleWellPressureRelations( real64 const & time_n, - real64 const & dt, - WellElementSubRegion const & subRegion, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) override; - - - /** - * @brief assembles the pressure relations at all connections between well elements except at the well head - * @param time_n time at the beginning of the time step - * @param dt the time step size - * @param domain the physical domain object - * @param dofManager degree-of-freedom manager associated with the linear system - * @param matrix the system matrix - * @param rhs the system right-hand side vector - */ - virtual void assemblePressureRelations( real64 const & time_n, - real64 const & dt, - DomainPartition const & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) override; - - /** - * @brief assembles the volume balance terms for all well elements - * @param domain the physical domain object - * @param dofManager degree-of-freedom manager associated with the linear system - * @param matrix the system matrix - * @param rhs the system right-hand side vector - */ - void assembleVolumeBalanceTerms( DomainPartition const & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ); - - /** - * @brief Initialize all the primary and secondary variables in all the wells - * @param domain the domain containing the well manager to access individual wells - */ - void initializeWells( DomainPartition & domain, real64 const & time_n ) override; - void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) override; - /* * @brief apply a special treatment to the wells that are shut - * @param time_n the time at the previous converged time step - * @param domain the physical domain object + * @param dofManager degree-of-freedom manager associated with the linear system * @param matrix the system matrix * @param rhs the system right-hand side vector */ - void shutDownWell( real64 const time_n, - DomainPartition const & domain, + void shutDownWell( WellElementSubRegion & subRegion, DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ); - struct viewKeyStruct : WellSolverBase::viewKeyStruct + struct viewKeyStruct : WellControls::viewKeyStruct { static constexpr char const * dofFieldString() { return "singlePhaseWellVars"; } @@ -371,10 +298,7 @@ class SinglePhaseWell : public WellSolverBase void saveState( WellElementSubRegion & subRegion ); - void printRates( real64 const & time_n, - real64 const & dt, - DomainPartition & domain ) override; - + virtual void postRestartInitialization( )override; /// flag if negative pressure is allowed integer m_allowNegativePressure; @@ -394,14 +318,12 @@ class SinglePhaseWell : public WellSolverBase WellElementSubRegion const & subRegion ) override; - virtual bool evaluateConstraints( real64 const & time_n, - WellElementSubRegion & subRegion ) override; /** * @brief Create well separator */ - void createSeparator(); + virtual void createSeparator( WellElementSubRegion & subRegion ) override; }; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index 1fe7c5c6a3b..2c408fa70ba 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -22,6 +22,7 @@ #include "WellConstants.hpp" #include "dataRepository/InputFlags.hpp" #include "functions/FunctionManager.hpp" +#include "mesh/PerforationFields.hpp" namespace geos @@ -30,8 +31,14 @@ namespace geos using namespace dataRepository; WellControls::WellControls( string const & name, Group * const parent ) - : PhysicsSolverBase( name, parent ), + : Group( name, parent ), m_type( Type::PRODUCER ), + m_numPhases( 0 ), + m_numComponents( 0 ), + m_numDofPerWellElement( 0 ), + m_numDofPerResElement( 0 ), + m_isThermal( 0 ), + m_keepVariablesConstantDuringInitStep( false ), m_inputControl( Control::UNINITIALIZED ), m_currentControl( Control::UNINITIALIZED ), m_useSurfaceConditions( 0 ), @@ -51,6 +58,18 @@ WellControls::WellControls( string const & name, Group * const parent ) setInputFlag( InputFlags::REQUIRED ). setDescription( "Well type. Valid options:\n* " + EnumStrings< Type >::concat( "\n* " ) ); + + + this->registerWrapper( viewKeyStruct::writeCSVFlagString(), &m_writeCSV ). + setApplyDefaultValue( 0 ). + setInputFlag( dataRepository::InputFlags::OPTIONAL ). + setDescription( "When set to 1, write the rates into a CSV file." ); + + this->registerWrapper( viewKeyStruct::timeStepFromTablesFlagString(), &m_timeStepFromTables ). + setApplyDefaultValue( 0 ). + setInputFlag( dataRepository::InputFlags::OPTIONAL ). + setDescription( "Choose time step to honor rates/bhp tables time intervals" ); + registerWrapper( viewKeyStruct::currentControlString(), &m_currentControl ). setDefaultValue( Control::UNINITIALIZED ). setInputFlag( InputFlags::FALSE ). @@ -100,6 +119,13 @@ WellControls::WellControls( string const & name, Group * const parent ) " - Injector pressure at reference depth initialized as: (1+initialPressureCoefficient)*reservoirPressureAtClosestPerforation + density*g*( zRef - zPerf ) \n" " - Producer pressure at reference depth initialized as: (1-initialPressureCoefficient)*reservoirPressureAtClosestPerforation + density*g*( zRef - zPerf ) " ); + registerWrapper( viewKeyStruct::targetRegionsString(), &m_targetRegionNames ). + setRTTypeName( rtTypes::CustomTypes::groupNameRefArray ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Allowable regions that the solver may be applied to. Note that this does not indicate that " + "the solver will be applied to these regions, only that allocation will occur such that the " + "solver may be applied to these regions. The decision about what regions this solver will be" + "applied to rests in the EventManager." ); addLogLevel< logInfo::WellControl >(); } @@ -110,7 +136,7 @@ WellControls::~WellControls() Group * WellControls::createChild( string const & childKey, string const & childName ) { - Group * baseChild = PhysicsSolverBase::createChild( childKey, childName ); + Group * baseChild = Group::createChild( childKey, childName ); if( baseChild != nullptr ) { return baseChild; @@ -214,7 +240,7 @@ TableFunction * createWellTable( string const & tableName, void WellControls::postInputInitialization() { - PhysicsSolverBase::postInputInitialization(); + Group::postInputInitialization(); // 0) Assign the value of the current well control // When the simulation starts from a restart file, we don't want to use the inputControl, // because the control may have switched in the simulation that generated the restart @@ -288,7 +314,10 @@ void WellControls::postInputInitialization() } } +void WellControls::postRestartInitialization( ) +{ +} void WellControls::setWellStatus( real64 const & currentTime, WellControls::Status status ) { m_wellStatus = status; @@ -453,4 +482,76 @@ real64 WellControls::getReferenceElevation() const } return getMaxBHPConstraint()->getReferenceElevation(); } +void WellControls::implicitStepSetup( real64 const & time_n, + real64 const & GEOS_UNUSED_PARAM( dt ), + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion ) +{ + // Set perforation status + setPerforationStatus( time_n, subRegion ); +} +void WellControls::setPerforationStatus( real64 const & time_n, WellElementSubRegion & subRegion ) +{ + FunctionManager & functionManager = FunctionManager::getInstance(); + + // Set perforation status + + PerforationData & perforationData = *subRegion.getPerforationData(); + string_array const & perfStatusTableName = perforationData.getPerfStatusTableName(); + arrayView1d< integer > perfStatus = perforationData.getLocalPerfStatus(); + // for now set to open + for( integer i=0; i( perfStatusTableName[i] ); + perfStatus[i]=PerforationData::PerforationStatus::OPEN; + if( tableFunction->evaluate( &time_n ) < LvArray::NumericLimits< real64 >::epsilon ) + { + perfStatus[i]=PerforationData::PerforationStatus::CLOSED; + } + } + + array1d< localIndex > const perfWellElemIndex = perforationData.getField< fields::perforation::wellElementIndex >(); + // global index local elements (size == subregion.size) + arrayView1d< globalIndex const > globalWellElementIndex = subRegion.getGlobalWellElementIndex(); + + arrayView1d< integer const > const elemGhostRank = subRegion.ghostRank(); + array1d< integer > & currentStatus = subRegion.getWellElementStatus(); + // Local elements + array1d< integer > & localElemStatus = subRegion.getWellLocalElementStatus(); + + integer numLocalElements = subRegion.getNumLocalElements(); + array1d< integer > segStatus( numLocalElements ); + + // Local perforations + for( integer j = 0; j < perforationData.size(); j++ ) + { + localIndex const iwelem = perfWellElemIndex[j]; + if( elemGhostRank[iwelem] < 0 ) + { + if( perfStatus[j] ) + { + segStatus[iwelem] +=1; + } + } + } + // Broadcast segment status so all cores have same well status + subRegion.setElementStatus( segStatus ); + integer numOpenElements = 0; + array1d< integer > const & updatedStatus = subRegion.getWellElementStatus(); + for( integer i=0; i0 ? setWellStatus( time_n, WellControls::Status::OPEN ) : setWellStatus( time_n, WellControls::Status::CLOSED ); + + + // Set local well element status array + for( integer i=0; i const & localMatrix, + arrayView1d< real64 > const & localRhs ) = 0; + /** + * @brief assembles the well momentum terms for an individual well + * @param time_n time at the beginning of the time step + * @param dt the time step size + * @param subRegion the well subregion containing all the primary and dependent fields + * @param dofManager degree-of-freedom manager associated with the linear system + * @param matrix the system matrix + * @param rhs the system right-hand side vector + */ + virtual void assembleWellPressureRelations( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) = 0; + /** + * @brief assembles the well constraint terms for an individual well + * @param time_n time at the beginning of the time step + * @param dt the time step size + * @param subRegion the well subregion containing all the primary and dependent fields + * @param dofManager degree-of-freedom manager associated with the linear system + * @param matrix the system matrix + * @param rhs the system right-hand side vector + */ + virtual void assembleWellConstraintTerms( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) = 0; + + /** + * @brief Recompute the perforation rates for all the wells + * @param time_n the time at the beginning of the time step + * @param dt the time step size + * @param elemManager the element region manager + * @param subRegion the well subregion containing all the primary and dependent fields + */ + virtual void computeWellPerforationRates( real64 const & time_n, + real64 const & GEOS_UNUSED_PARAM( dt ), + ElementRegionManager const & elemManager, + WellElementSubRegion & subRegion ) = 0; + + /** + * @brief assembles the flux terms for individual well for all connections between well elements + * @param time_n previous time value + * @param dt time step + * @param subRegion the well subregion containing all the primary and dependent fields + * @param dofManager degree-of-freedom manager associated with the linear system + * @param matrix the system matrix + * @param rhs the system right-hand side vector + */ + virtual void assembleWellFluxTerms( real64 const & time, + real64 const & dt, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) = 0; + virtual real64 + calculateWellResidualNorm( real64 const & time_n, + real64 const & dt, + NonlinearSolverParameters const & nonlinearSolverParameters, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs ) = 0; + + virtual array1d< real64 > + calculateLocalWellResidualNorm( real64 const & time_n, + real64 const & dt, + NonlinearSolverParameters const & nonlinearSolverParameters, + WellElementSubRegion const & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs ) = 0; + + virtual real64 + scalingForWellSystemSolution( WellElementSubRegion & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution ) = 0; + + virtual bool + checkWellSystemSolution( WellElementSubRegion & subRegion, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor ) = 0; + + virtual void + applyWellSystemSolution( DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor, + real64 const dt, + DomainPartition & domain, + MeshLevel & mesh, + WellElementSubRegion & subRegion ) = 0; + + /** + * @brief Recompute all dependent quantities from primary variables (including constitutive models) + * @param subRegion the well subregion containing all the primary and dependent fields + */ + virtual real64 updateWellState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) = 0; + + /** + * @brief Reset the well state to the beginning of the time step + * @param subRegion the well subregion containing all the primary and dependent fields + */ + virtual void resetStateToBeginningOfStep( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) = 0; + + virtual void postInputInitialization() override; + + virtual void initializeWellPostInitialConditionsPreSubGroups( WellElementSubRegion & subRegion ) = 0; + virtual void printRates( real64 const & time_n, + real64 const & dt, + WellElementSubRegion const & subRegion ) = 0; + /**@}*/ /** * @brief Apply a given functor to a container if the container can be * cast to one of the specified types. @@ -256,6 +437,44 @@ class WellControls : public PhysicsSolverBase */ ///@{ + /** + * @brief Get the Constitutive Name object + * + * @tparam CONSTITUTIVE_BASE_TYPE the base type of the constitutive model. + * @param subRegion the element subregion on which the constitutive model is registered + * @return the name name of the constitutive model of type CONSTITUTIVE_BASE_TYPE registered on the subregion. + */ + template< typename CONSTITUTIVE_BASE_TYPE > + static string getConstitutiveName( ElementSubRegionBase const & subRegion ); + + /** + * @brief Register wrapper with given name and store constitutive model name on the subregion + * + * @tparam CONSTITUTIVE the base type of the constitutive model. + * @param subRegion the subregion on which the constitutive model is registered. + * @param wrapperName the wrapper name to register. + * @param constitutiveType the type description of the constitutive model. + */ + template< typename CONSTITUTIVE > + void setConstitutiveName( ElementSubRegionBase & subRegion, string const & wrapperName, string const & constitutiveType ) const; + + /** + * @brief return the list of target regions + * @return the array of region names + */ + string_array const & getTargetRegionNames() const {return m_targetRegionNames;} + /** + * @brief Get the control type for the well. + * @return the Control enum enforced at the well + */ + std::string getFlowSolverName() const { return m_flowSolverName; } + + /** + * @brief Set the control type for the well. + * @param[in] flowSolverName the name of the flow solver + */ + void setFlowSolverName( const std::string & flowSolverName ) { m_flowSolverName = flowSolverName; } + /** * @brief Get the control type for the well. * @return the Control enum enforced at the well @@ -328,7 +547,7 @@ class WellControls : public PhysicsSolverBase * @brief Getter for the reservoir region associated with reservoir volume constraint * @return name of reservoir region */ - string referenceReservoirRegion() const { return m_referenceReservoirRegion; } + string getReferenceReservoirRegion() const { return m_referenceReservoirRegion; } /** * @brief Getter for the surface pressure when m_useSurfaceConditions == 1 @@ -354,6 +573,18 @@ class WellControls : public PhysicsSolverBase */ bool isProducer() const { return ( m_type == Type::PRODUCER ); } + /** + * @brief getter for iso/thermal switch + * @return True if thermal + */ + integer isThermal() const { return m_isThermal; } + + /** + * @brief setter for iso/thermal switch + * @param[in] isThermal + */ + + void setThermal( bool isThermal ) { m_isThermal=isThermal; } /** * @brief Is the well open (or shut) at currentTime, status initalized in WellSolverBase::implicitStepSetup * @return a boolean @@ -402,6 +633,16 @@ class WellControls : public PhysicsSolverBase * @param[inout] nextDt the time step */ void setNextDtFromTables( real64 const & currentTime, real64 & nextDt ); + /** + * @brief Utility function to keep the well variables during a time step (used in + * poromechanics simulations) + * @param[in] keepVariablesConstantDuringInitStep flag to tell the solver to freeze its + * primary variables during a time step + * @detail This function is meant to be called by a specific task before/after the + * initialization step + */ + void setKeepVariablesConstantDuringInitStep( bool const keepVariablesConstantDuringInitStep ) + { m_keepVariablesConstantDuringInitStep = keepVariablesConstantDuringInitStep; } /** @@ -460,12 +701,27 @@ class WellControls : public PhysicsSolverBase ///@} + virtual string wellElementDofName() const = 0; + + virtual string resElementDofName() const = 0; + + virtual localIndex numFluidComponents() const = 0; + + virtual localIndex numFluidPhases() const = 0; /** * @brief Struct to serve as a container for variable strings and keys. * @struct viewKeyStruct */ struct viewKeyStruct { + /// String key for the fluid model names + static constexpr char const * fluidNamesString() { return "fluidNames"; } + /// String key for the write CSV flag + static constexpr char const * writeCSVFlagString() { return "writeCSV"; } + static constexpr char const * timeStepFromTablesFlagString() { return "timeStepFromTables"; } +/// @return string for the targetRegions wrapper + static constexpr char const * targetRegionsString() { return "targetRegions"; } + /// String key for the well reference elevation (for BHP control) static constexpr char const * refElevString() { return "referenceElevation"; } /// String key for the well type @@ -515,6 +771,13 @@ class WellControls : public PhysicsSolverBase } /// ViewKey struct for the WellControls class viewKeysWellControls; + void setPerforationStatus( real64 const & time_n, WellElementSubRegion & subRegion ); + /** + * @brief Set next time step based on a table function + * @param[in] table the table function + * @param[in] currentTime the current time + * @param[inout] nextDt the time step + */ static void setNextDtFromTable( TableFunction const * table, real64 const currentTime, real64 & nextDt ); @@ -541,15 +804,44 @@ class WellControls : public PhysicsSolverBase std::vector< WellConstraintBase * > getProdRateConstraints() const { return m_productionRateConstraintList; }; std::vector< WellConstraintBase * > getInjRateConstraints() { return m_injectionRateConstraintList; } std::vector< WellConstraintBase * > getInjRateConstraints() const { return m_injectionRateConstraintList; } -protected: - virtual void postInputInitialization() override; +protected: + virtual void postRestartInitialization( )override; private: + /// List of names of regions the solver will be applied to + string_array m_targetRegionNames; + +protected: /// Well type (as Type enum) Type m_type; + /// Name of the flow solver managing this well + std::string m_flowSolverName; + + /// the max number of fluid phases + integer m_numPhases; + + /// the number of fluid components + integer m_numComponents; + + /// the number of Degrees of Freedom per well element + integer m_numDofPerWellElement; + + /// the number of Degrees of Freedom per reservoir element + integer m_numDofPerResElement; + + /// flag indicating whether thermal formulation is used + integer m_isThermal; + /// flag to freeze the initial state during initialization in coupled problems + bool m_keepVariablesConstantDuringInitStep; + /// rates output + integer m_writeCSV; + string const m_ratesOutputDir; + + // flag to enable time step selection base on rates/bhp tables coordinates + integer m_timeStepFromTables; /// Reference elevation real64 m_refElevation; @@ -568,6 +860,9 @@ class WellControls : public PhysicsSolverBase // Fuild model to compute properties for constraint equation user specified conditions std::unique_ptr< constitutive::ConstitutiveBase > m_fluidSeparatorPtr; + /// name of the fluid constitutive model used as a reference for component/phase description on subregion + string m_referenceFluidModelName; + /// Reservoir region associated with reservoir volume constraint string m_referenceReservoirRegion; @@ -633,6 +928,62 @@ ENUM_STRINGS( WellControls_Control, "uninitialized" ); +template< typename CONSTITUTIVE > +void WellControls::setConstitutiveName( ElementSubRegionBase & subRegion, string const & wrapperName, string const & constitutiveType ) const +{ + subRegion.registerWrapper< string >( wrapperName ). + setPlotLevel( dataRepository::PlotLevel::NOPLOT ). + setRestartFlags( dataRepository::RestartFlags::NO_WRITE ). + setSizedFromParent( 0 ); + + string & constitutiveName = subRegion.getReference< string >( wrapperName ); + constitutiveName = getConstitutiveName< CONSTITUTIVE >( subRegion ); + GEOS_ERROR_IF( constitutiveName.empty(), GEOS_FMT( "{}: {} constitutive model not found on subregion {}", + getDataContext(), constitutiveType, subRegion.getName() ) ); +} +template< typename CONSTITUTIVE_BASE_TYPE > +string WellControls::getConstitutiveName( ElementSubRegionBase const & subRegion ) +{ + string validName; + dataRepository::Group const & constitutiveModels = subRegion.getConstitutiveModels(); + + constitutiveModels.forSubGroups< CONSTITUTIVE_BASE_TYPE >( [&]( dataRepository::Group const & model ) + { + GEOS_ERROR_IF( !validName.empty(), "A valid constitutive model was already found." ); + validName = model.getName(); + } ); + + return validName; +} + +/** + * @brief Get the Constitutive Model object + * @tparam BASETYPE the base type of the constitutive model. + * @tparam LOOKUP_TYPE the type of the key used to look up the constitutive model. + * @param dataGroup the data group containing the constitutive models. + * @param key the key used to look up the constitutive model. + * @return the constitutive model of type @p BASETYPE registered on the @p dataGroup with the key @p key. + */ +template< typename BASETYPE = constitutive::ConstitutiveBase, typename LOOKUP_TYPE > +static BASETYPE const & getConstitutiveModel( dataRepository::Group const & dataGroup, LOOKUP_TYPE const & key ) +{ + dataRepository::Group const & constitutiveModels = dataGroup.getGroup( ElementSubRegionBase::groupKeyStruct::constitutiveModelsString() ); + return constitutiveModels.getGroup< BASETYPE >( key ); +} +/** + * @brief Get the Constitutive Model object + * @tparam BASETYPE the base type of the constitutive model. + * @tparam LOOKUP_TYPE the type of the key used to look up the constitutive model. + * @param dataGroup the data group containing the constitutive models. + * @param key the key used to look up the constitutive model. + * @return the constitutive model of type @p BASETYPE registered on the @p dataGroup with the key @p key. + */ +template< typename BASETYPE = constitutive::ConstitutiveBase, typename LOOKUP_TYPE > +static BASETYPE & getConstitutiveModel( dataRepository::Group & dataGroup, LOOKUP_TYPE const & key ) +{ + dataRepository::Group & constitutiveModels = dataGroup.getGroup( ElementSubRegionBase::groupKeyStruct::constitutiveModelsString() ); + return constitutiveModels.getGroup< BASETYPE >( key ); +} } //namespace geos #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLCONTROLS_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp index 7ba11d60d11..043215670b9 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp @@ -23,10 +23,13 @@ #include "mesh/PerforationFields.hpp" #include "mesh/WellElementRegion.hpp" #include "mesh/WellElementSubRegion.hpp" +#include "physicsSolvers/LogLevelsInfo.hpp" #include "physicsSolvers/fluidFlow/wells/LogLevelsInfo.hpp" #include "physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp" +#include "physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWellFields.hpp" #include "physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp" -#include "physicsSolvers/fluidFlow/wells/WellSolverBase.hpp" +#include "physicsSolvers/fluidFlow/wells/WellControls.hpp" + #include "physicsSolvers/fluidFlow/wells/WellSolverBaseFields.hpp" #include "fileIO/Outputs/OutputBase.hpp" #include "functions/FunctionManager.hpp" @@ -42,7 +45,9 @@ WellManager::WellManager( string const & name, m_useMass( false ), m_useTotalMassEquation( 1 ), m_isThermal( 0 ), - m_isCompositional( true ) + m_isCompositional( true ), + m_minScalingFactor( 0.01 ), + m_allowCompDensChopping( 1 ) { this->getWrapper< string >( viewKeyStruct::discretizationString() ). setInputFlag( InputFlags::FALSE ); @@ -63,6 +68,13 @@ WellManager::WellManager( string const & name, setInputFlag( InputFlags::OPTIONAL ). setDescription( "Use total mass equation" ); + this->registerWrapper( viewKeyStruct::allowLocalCompDensChoppingString(), &m_allowCompDensChopping ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( 1 ). + setDescription( "Flag indicating whether local (cell-wise) chopping of negative compositions is allowed" ); + + } Group * WellManager::createChild( string const & childKey, string const & childName ) { @@ -102,6 +114,8 @@ void WellManager::registerDataOnMesh( Group & meshBodies ) { if( isCompositional() ) { + //std::string const & flowSolverName = getParent().getName();//getGroup< CompositionalMultiphaseBase >().getName(); + // CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); forDiscretizationOnMeshTargets( meshBodies, [&] ( string const &, MeshLevel & mesh, @@ -115,7 +129,9 @@ void WellManager::registerDataOnMesh( Group & meshBodies ) WellElementSubRegion & subRegion ) { CompositionalMultiphaseWell & well = getCompositionalMultiphaseWell( subRegion ); + //well.setFlowSolverName( flowSolver.getName() ); well.registerWellDataOnMesh( subRegion ); + well.setThermal( isThermal() ); m_numFluidPhases = well.numFluidPhases(); m_numFluidComponents = well.numFluidComponents(); } ); @@ -285,9 +301,9 @@ void WellManager::registerDataOnMesh( Group & meshBodies ) #endif } -WellSolverBase & WellManager::getWell( WellElementSubRegion const & subRegion ) +WellControls & WellManager::getWell( WellElementSubRegion const & subRegion ) { - return this->getGroup< WellSolverBase >( subRegion.getWellControlsName()); + return this->getGroup< WellControls >( subRegion.getWellControlsName()); } void WellManager::implicitStepSetup( real64 const & time_n, @@ -307,8 +323,9 @@ void WellManager::implicitStepSetup( real64 const & time_n, WellElementSubRegion & subRegion ) { - WellSolverBase & well = getWell( subRegion ); - well.implicitStepSetup( time_n, dt, domain ); + WellControls & well = getWell( subRegion ); + //well.implicitStepSetup( time_n, dt, domain ); + well.implicitStepSetup( time_n, dt, elemManager, subRegion ); } ) ; } ); @@ -335,7 +352,10 @@ string WellManager::wellElementDofName() const string WellManager::resElementDofName() const { - return "reservoirCouplingVars"; + if( isCompositional() ) + return CompositionalMultiphaseBase::viewKeyStruct::elemDofFieldString(); + else + return SinglePhaseBase::viewKeyStruct::elemDofFieldString(); } localIndex WellManager::numFluidComponents() const @@ -402,5 +422,630 @@ void WellManager::initializePostSubGroups() #endif } +void WellManager::setupDofs( DomainPartition const & domain, + DofManager & dofManager ) const +{ + map< std::pair< string, string >, string_array > meshTargets; + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel const & meshLevel, + string_array const & regionNames ) + { + string_array regions; + ElementRegionManager const & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion const & region ) + { + regions.emplace_back( region.getName() ); + } ); + auto const key = std::make_pair( meshBodyName, meshLevel.getName()); + meshTargets[key] = std::move( regions ); + } ); + + dofManager.addField( wellElementDofName(), + FieldLocation::Elem, + numDofPerWellElement(), + meshTargets ); + + dofManager.addCoupling( wellElementDofName(), + wellElementDofName(), + DofManager::Connector::Node ); +} + +void WellManager::assembleSystem( real64 const time, + real64 const dt, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + + + // selects constraints one of 2 ways + // wellEstimator flag set to 0 => orginal logic rates are computed during update state and constraints are selected every newton + // iteration + // wellEstimator flag > 0 => well esitmator solved for each constraint and then selects the constraint + // => estimator solve only performed first "wellEstimator" iterations + NonlinearSolverParameters const & nonlinearParams = getNonlinearSolverParameters(); + selectWellConstraint( time, dt, nonlinearParams.m_numNewtonIterations, domain ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = getWellControls( subRegion ); + // assemble the accumulation term in the mass balance equations + wellControls.assembleWellAccumulationTerms( time, dt, subRegion, dofManager, localMatrix, localRhs ); + // assemble the pressure relations between well elements + wellControls.assembleWellPressureRelations( time, dt, subRegion, dofManager, localMatrix, localRhs ); + // assemble well constraint terms + wellControls.assembleWellConstraintTerms( time, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); + // compute the perforation rates (later assembled by the coupled solver) + wellControls.computeWellPerforationRates( time, dt, elementRegionManager, subRegion ); + // assemble the flux terms in the mass balance equations + wellControls.assembleWellFluxTerms( time, dt, subRegion, dofManager, localMatrix, localRhs ); + + } ); + } ); + + #if 0 + // assemble the accumulation term in the mass balance equations + assembleAccumulationTerms( time, dt, domain, dofManager, localMatrix, localRhs ); + + + + // then assemble the pressure relations between well elements + assemblePressureRelations( time, dt, domain, dofManager, localMatrix, localRhs ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + ElementRegionManager & elementRegionManager = mesh.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + assembleWellConstraintTerms( time, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); + } ); + } ); + + // then compute the perforation rates (later assembled by the coupled solver) + computePerforationRates( time, dt, domain ); + + // then assemble the flux terms in the mass balance equations + // get a reference to the degree-of-freedom numbers + // then assemble the flux terms in the mass balance equations + assembleFluxTerms( time, dt, domain, dofManager, localMatrix, localRhs ); +#endif +} + +void WellManager::selectWellConstraint( real64 const & time_n, + real64 const & dt, + const integer coupledIterationNumber, + DomainPartition & domain ) +{ + GEOS_MARK_FUNCTION; + GEOS_UNUSED_VAR( dt ); + GEOS_UNUSED_VAR( coupledIterationNumber ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = getWellControls( subRegion ); + // Intiialize well if it is open + // Well state estimated from reservoir conditions + if( wellControls.isWellOpen() ) + { + if( !wellControls.getWellState() ) + { + wellControls.setWellState( 1 ); + + wellControls.initializeWell( domain, meshLevel, subRegion, time_n ); + } + } + else + { + wellControls.setWellState( 0 ); + } + + if( wellControls.getWellState()) + { + wellControls.evaluateConstraints( time_n, + subRegion ); + + // If a well is opened and then timestep is cut resulting in the well being shut, if the well is opened + // the well initialization code requires control type to by synced + integer owner = -1; + // Only subregion owner evaluates well control and control changes need to be broadcast to all ranks + if( subRegion.isLocallyOwned() ) + { + owner = MpiWrapper::commRank( MPI_COMM_GEOS ); + } + owner = MpiWrapper::max( owner ); + WellControls::Control wellControl = wellControls.getControl(); + MpiWrapper::broadcast( wellControl, owner ); + wellControls.setControl( wellControl ); + } + } ); + } ); + +} + +void WellManager::resetStateToBeginningOfStep( DomainPartition & domain ) +{ + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + + ElementRegionManager & elemManager = mesh.getElemManager(); + + elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + WellControls & wellControls = getWellControls( subRegion ); + wellControls.resetStateToBeginningOfStep( elemManager, subRegion ); + + + } ); + } ); +} + +void WellManager::implicitStepComplete( real64 const & time, + real64 const & dt, + DomainPartition & domain ) +{ + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + + ElementRegionManager & elemManager = mesh.getElemManager(); + + elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + WellControls & wellControls = getWellControls( subRegion ); + wellControls.implicitStepComplete( time, dt, subRegion ); + } ); + } ); +} + +void WellManager::postRestartInitialization() +{ +#if 0 + DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + // loop over the wells + mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, + WellElementSubRegion & subRegion ) + + { + WellControls & wellControls = getWell( subRegion ); + wellControls.postRestartInitialization( ); + + } ); + } ); +#endif +} +void WellManager::initializePostInitialConditionsPreSubGroups() +{ + PhysicsSolverBase::initializePostInitialConditionsPreSubGroups(); + DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); + forDiscretizationOnMeshTargets ( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + + // loop over the wells + mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + + WellControls & wellControls = getWellControls( subRegion ); + wellControls.initializeWellPostInitialConditionsPreSubGroups( subRegion ); + + + } ); + } ); +} +void WellManager::setKeepVariablesConstantDuringInitStep( bool const keepVariablesConstantDuringInitStep ) +{ + DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + // loop over the wells + mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, + WellElementSubRegion & subRegion ) + + { + WellControls & wellControls = getWellControls( subRegion ); + wellControls.setKeepVariablesConstantDuringInitStep( keepVariablesConstantDuringInitStep ); + + } ); + } ); +} +void WellManager::updateState( DomainPartition & domain ) +{ + GEOS_MARK_FUNCTION; + //tjb + real64 maxPhaseVolFrac = 0.0; + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + ElementRegionManager & elemManager = mesh.getElemManager(); + elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + WellControls & wellControls = getWellControls( subRegion ); + if( wellControls.getWellState()) + { + + real64 const maxRegionPhaseVolFrac = wellControls.updateWellState( elemManager, subRegion ); + + maxPhaseVolFrac = LvArray::math::max( maxRegionPhaseVolFrac, maxPhaseVolFrac ); + } + } ); + } ); + maxPhaseVolFrac = MpiWrapper::max( maxPhaseVolFrac ); + + GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, + GEOS_FMT( " {}: Max well phase volume fraction change = {}", + getName(), fmt::format( "{:.{}f}", maxPhaseVolFrac, 4 ) ) ); + +} + +real64 +WellManager::calculateResidualNorm( real64 const & time_n, + real64 const & dt, + DomainPartition const & domain, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs ) +{ + GEOS_MARK_FUNCTION; + + integer numNorm = 1; // mass balance + array1d< real64 > localResidualNorm; + array1d< real64 > localResidualNormalizer; + + if( isThermal() ) + { + numNorm = 2; // mass balance and energy balance + } + localResidualNorm.resize( numNorm ); + localResidualNormalizer.resize( numNorm ); + + + globalIndex const rankOffset = dofManager.rankOffset(); + string const wellDofKey = dofManager.getKey( wellElementDofName() ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel const & mesh, + string_array const & regionNames ) + { + + + ElementRegionManager const & elemManager = mesh.getElemManager(); + + elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion const & subRegion ) + { + + WellControls & wellControls = getWellControls( subRegion ); + + // step 1: compute the norm in the subRegion + if( true ) // tjb wellControls.isWellOpen( ) ) + { + localResidualNorm = wellControls.calculateLocalWellResidualNorm( time_n, + dt, + m_nonlinearSolverParameters, + subRegion, + dofManager, + localRhs ); + } + else + { + for( integer i=0; i const & localSolution ) +{ + GEOS_MARK_FUNCTION; + + string const wellDofKey = dofManager.getKey( wellElementDofName() ); + + real64 scalingFactor = 1.0; + if( isCompositional() ) + { + + + real64 maxDeltaPres = 0.0, maxDeltaCompDens = 0.0, maxDeltaTemp = 0.0; + real64 minPresScalingFactor = 1.0, minCompDensScalingFactor = 1.0, minTempScalingFactor = 1.0; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + + ElementRegionManager & elemManager = mesh.getElemManager(); + elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + + { + CompositionalMultiphaseWell * wellControls = dynamic_cast< CompositionalMultiphaseWell * >(&getWellControls ( subRegion )); + wellControls->scalingForLocalSystemSolution( subRegion, + dofManager, + maxDeltaPres, + maxDeltaCompDens, + maxDeltaTemp, + minPresScalingFactor, + minCompDensScalingFactor, + minTempScalingFactor, + localSolution ); + + + } ); + } ); + + scalingFactor = MpiWrapper::min( scalingFactor ); + maxDeltaPres = MpiWrapper::max( maxDeltaPres ); + maxDeltaCompDens = MpiWrapper::max( maxDeltaCompDens ); + minPresScalingFactor = MpiWrapper::min( minPresScalingFactor ); + minCompDensScalingFactor = MpiWrapper::min( minCompDensScalingFactor ); + + string const massUnit = m_useMass ? "kg/m3" : "mol/m3"; + GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, + GEOS_FMT( " {}: Max well pressure change: {} Pa (before scaling)", + getName(), GEOS_FMT( "{:.{}f}", maxDeltaPres, 3 ) ) ); + GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, + GEOS_FMT( " {}: Max well component density change: {} {} (before scaling)", + getName(), GEOS_FMT( "{:.{}f}", maxDeltaCompDens, 3 ), massUnit ) ); + + if( m_isThermal ) + { + maxDeltaTemp = MpiWrapper::max( maxDeltaTemp ); + minTempScalingFactor = MpiWrapper::min( minTempScalingFactor ); + GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, + GEOS_FMT( " {}: Max well temperature change: {} K (before scaling)", + getName(), GEOS_FMT( "{:.{}f}", maxDeltaTemp, 3 ) ) ); + } + + + GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, + GEOS_FMT( " {}: Min well pressure scaling factor: {}", + getName(), minPresScalingFactor ) ); + GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, + GEOS_FMT( " {}: Min well component density scaling factor: {}", + getName(), minCompDensScalingFactor ) ); + if( m_isThermal ) + { + GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, + GEOS_FMT( " {}: Min well temperature scaling factor: {}", + getName(), minTempScalingFactor ) ); + } + + } + return LvArray::math::max( scalingFactor, m_minScalingFactor ); + +} + +bool +WellManager::checkSystemSolution( DomainPartition & domain, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor ) +{ + GEOS_MARK_FUNCTION; + + string const wellDofKey = dofManager.getKey( wellElementDofName() ); + integer globalCheck = 1; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + + ElementRegionManager & elemManager = mesh.getElemManager(); + elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + + { + + WellControls & wellControls = getWellControls( subRegion ); + integer localCheck = wellControls.checkWellSystemSolution( subRegion, dofManager, localSolution, scalingFactor ); + globalCheck = MpiWrapper::min( localCheck ); + } ); + } ); + return globalCheck; +} + +void +WellManager::applySystemSolution( DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor, + real64 const dt, + DomainPartition & domain ) +{ + + + DofManager::CompMask pressureMask( m_numDofPerWellElement, 0, 1 ); + + DofManager::CompMask connRateMask( m_numDofPerWellElement, numFluidComponents()+1, numFluidComponents()+2 ); + GEOS_UNUSED_VAR( dt ); + // update all the fields using the global damping coefficients + dofManager.addVectorToField( localSolution, + wellElementDofName(), + well::pressure::key(), + scalingFactor, + pressureMask ); + + dofManager.addVectorToField( localSolution, + wellElementDofName(), + well::mixtureConnectionRate::key(), + scalingFactor, + connRateMask ); + if( isCompositional()) + { + DofManager::CompMask componentMask( m_numDofPerWellElement, 1, numFluidComponents()+1 ); + dofManager.addVectorToField( localSolution, + wellElementDofName(), + well::globalCompDensity::key(), + scalingFactor, + componentMask ); + } + if( isThermal() ) + { + DofManager::CompMask temperatureMask( m_numDofPerWellElement, numFluidComponents()+2, numFluidComponents()+3 ); + + dofManager.addVectorToField( localSolution, + wellElementDofName(), + well::temperature::key(), + scalingFactor, + temperatureMask ); + + } + // if component density chopping is allowed, some component densities may be negative after the update + // these negative component densities are set to zero in this function + if( m_allowCompDensChopping ) + { + chopNegativeDensities( domain ); + } + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + stdVector< string > propNames; + propNames.emplace_back( well::pressure::key() ); + + propNames.emplace_back( well::mixtureConnectionRate::key() ); + if( isCompositional()) + { + propNames.emplace_back( well::globalCompDensity::key() ); + } + if( isThermal() ) + { + propNames.emplace_back( well::temperature::key() ); + } + // synchronize + FieldIdentifiers fieldsToBeSync; + + fieldsToBeSync.addElementFields( propNames, + regionNames ); + + + CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, + mesh, + domain.getNeighbors(), + true ); + } ); + +} + +void WellManager::chopNegativeDensities( DomainPartition & domain ) +{ + integer const numComp = m_numFluidComponents; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + + ElementRegionManager & elemManager = mesh.getElemManager(); + + elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + arrayView1d< integer const > const & wellElemGhostRank = subRegion.ghostRank(); + + arrayView2d< real64, compflow::USD_COMP > const & wellElemCompDens = + subRegion.getField< well::globalCompDensity >(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) + { + if( wellElemGhostRank[iwelem] < 0 ) + { + for( integer ic = 0; ic < numComp; ++ic ) + { + // we allowed for some densities to be slightly negative in CheckSystemSolution + // if the new density is negative, chop back to zero + if( wellElemCompDens[iwelem][ic] < 0 ) + { + wellElemCompDens[iwelem][ic] = 0; + } + } + } + } ); + } ); + + } ); +} + REGISTER_CATALOG_ENTRY( PhysicsSolverBase, WellManager, string const &, Group * const ) -} // namespace geos +} // namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp index b2c04666266..8b5e1d00307 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp @@ -21,8 +21,10 @@ #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELL_MANAGER_HPP_ #include "physicsSolvers/PhysicsSolverBase.hpp" -#include "physicsSolvers/fluidFlow/wells/WellSolverBase.hpp" +#include "physicsSolvers/fluidFlow/SinglePhaseBase.hpp" +#include "physicsSolvers/fluidFlow/CompositionalMultiphaseBase.hpp" #include "physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp" +#include "physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp" namespace geos { @@ -49,7 +51,7 @@ class WellManager : public PhysicsSolverBase public: /// String used to form the solverName used to register single-physics solvers in CoupledSolver - static string coupledSolverAttributePrefix() { return "well"; } + static string coupledSolverAttributePrefix() { return "wellManager"; } /** * @brief main constructor for Group Objects @@ -100,16 +102,6 @@ class WellManager : public PhysicsSolverBase */ bool isCompositional() const { return m_isCompositional; } - /** - * @brief Utility function to keep the well variables during a time step (used in - * poromechanics simulations) - * @param[in] keepVariablesConstantDuringInitStep flag to tell the solver to freeze its - * primary variables during a time step - * @detail This function is meant to be called by a specific task before/after the - * initialization step - */ - void setKeepVariablesConstantDuringInitStep( bool const keepVariablesConstantDuringInitStep ) - { m_keepVariablesConstantDuringInitStep = keepVariablesConstantDuringInitStep; } /** * @brief getter for the name of the flow solver (used in UpdateState) @@ -134,7 +126,7 @@ class WellManager : public PhysicsSolverBase * @param subRegion the well subRegion whose well solver is requested * @return a reference to the well solver */ - WellSolverBase & getWell( WellElementSubRegion const & subRegion ); + WellControls & getWell( WellElementSubRegion const & subRegion ); /** * @brief get the name of DOF defined on well elements @@ -147,8 +139,12 @@ class WellManager : public PhysicsSolverBase static constexpr char const * dofFieldString() { return "wellVars"; } static constexpr char const * isThermalString() { return "isThermal"; } static constexpr char const * useMassFlagString() {return "useMass"; } + /// @return string for the nextDt targetRegions wrapper + static constexpr char const * targetRegionsString() { return "targetRegions"; } static constexpr char const * useTotalMassEquationString() { return "useTotalMassEquation"; } + static constexpr char const * allowLocalCompDensChoppingString() { return CompositionalMultiphaseBase::viewKeyStruct::allowLocalCompDensChoppingString(); } + }; @@ -223,8 +219,23 @@ class WellManager : public PhysicsSolverBase */ CompositionalMultiphaseWell const & getCompositionalMultiphaseWell( WellElementSubRegion const & subRegion ) const; - + /** + * @brief Selects the active well constraint based on current conditions + * @param[in] currentTime the current time + * @param[in] currentDt the current time step size + * @param[in] coupledIterationNumber the current coupled iteration number + * @param[in] domain the domain object + * @return the prescribed time step size + */ + void selectWellConstraint( real64 const & time_n, + real64 const & dt, + integer const coupledIterationNumber, + DomainPartition & domain ); /* PhysicsSolverBase interfaces */ + + virtual void setupDofs( DomainPartition const & domain, + DofManager & dofManager ) const override; + /** * @brief function to perform setup for implicit timestep * @param time_n the time at the beginning of the step @@ -242,7 +253,7 @@ class WellManager : public PhysicsSolverBase real64 const & dt, DomainPartition & domain ) override; -#if 0 + /** * @brief function to assemble the linear system matrix and rhs * @param time the time at the beginning of the step @@ -267,8 +278,105 @@ class WellManager : public PhysicsSolverBase DomainPartition & domain, DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ); + arrayView1d< real64 > const & localRhs ) override; + + + virtual void + resetStateToBeginningOfStep( DomainPartition & domain ) override; + + virtual void + implicitStepComplete( real64 const & time, + real64 const & dt, + DomainPartition & domain ) override; + + /** + * @brief calculate the norm of the global system residual + * @param time the time at the beginning of the step + * @param dt the desired timestep + * @param domain the domain partition + * @param dofManager degree-of-freedom manager associated with the linear system + * @param localRhs the system right-hand side vector + * @return norm of the residual + * + * This function returns the norm of global residual vector, which is suitable for comparison with + * a tolerance. + */ + virtual real64 + calculateResidualNorm( real64 const & time, + real64 const & dt, + DomainPartition const & domain, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs ) override; + /** + * @brief Recompute all dependent quantities from primary variables (including constitutive models) + * @param domain the domain containing the mesh and fields + */ + virtual void updateState( DomainPartition & domain ) override; + + /** + * @brief Function to determine if the solution vector should be scaled back in order to maintain a known constraint. + * @param[in] domain The domain partition. + * @param[in] dofManager degree-of-freedom manager associated with the linear system + * @param[in] localSolution the solution vector + * @return The factor that should be used to scale the solution vector values when they are being applied. + */ + virtual real64 + scalingForSystemSolution( DomainPartition & domain, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution )override; + + /** + * @brief Function to check system solution for physical consistency and constraint violation + * @param domain the domain partition + * @param dofManager degree-of-freedom manager associated with the linear system + * @param localSolution the solution vector + * @param scalingFactor factor to scale the solution prior to application + * @return true if solution can be safely applied without violating physical constraints, false otherwise + * + * @note This function must be overridden in the derived physics solver in order to use an implict + * solution method such as LinearImplicitStep() or NonlinearImplicitStep(). + * + */ + virtual bool + checkSystemSolution( DomainPartition & domain, + DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor ) override; + /** + * @brief Function to apply the solution vector to the state + * @param dofManager degree-of-freedom manager associated with the linear system + * @param localSolution the solution vector + * @param scalingFactor factor to scale the solution prior to application + * @param dt the timestep + * @param domain the domain partition + * + * This function performs 2 operations: + * 1) extract the solution vector for the "blockSystem" parameter, and applies the + * contents of the solution vector to the primary variable field data, + * 2) perform a synchronization of the primary field variable such that all ghosts are updated, + * + * The "scalingFactor" parameter allows for the scaled application of the solution vector. For + * instance, a line search may apply a negative scaling factor to remove part of the previously + * applied solution. + * + * @note This function must be overridden in the derived physics solver in order to use an implict + * solution method such as LinearImplicitStep() or NonlinearImplicitStep(). + * + */ + virtual void + applySystemSolution( DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor, + real64 const dt, + DomainPartition & domain ) override; + + /** + * @brief Sets all the negative component densities (if any) to zero. + * @param domain the physical domain object + */ + void chopNegativeDensities( DomainPartition & domain ); +#if 0 /** * @brief calculate the norm of the global system residual * @param time the time at the beginning of the step @@ -371,14 +479,27 @@ class WellManager : public PhysicsSolverBase DomainPartition & domain ) override; #endif + + /** + * @brief Utility function to keep the well variables during a time step (used in + * poromechanics simulations) + * @param[in] keepVariablesConstantDuringInitStep flag to tell the solver to freeze its + * primary variables during a time step + * @detail This function is meant to be called by a specific task before/after the + * initialization step + */ + void setKeepVariablesConstantDuringInitStep( bool const keepVariablesConstantDuringInitStep ); + + protected: //virtual void postInputInitialization() override; virtual void initializePostSubGroups() override; - //virtual void initializePostInitialConditionsPreSubGroups() override; + virtual void initializePostInitialConditionsPreSubGroups() override; + + virtual void postRestartInitialization() override final; - // virtual void postRestartInitialization() override final; private: @@ -397,8 +518,6 @@ class WellManager : public PhysicsSolverBase /// flag indicating whether compositional formulation is used bool m_isCompositional; - /// flag to freeze the initial state during initialization in coupled problems - bool m_keepVariablesConstantDuringInitStep; /// number of phases integer m_numFluidPhases; @@ -411,6 +530,12 @@ class WellManager : public PhysicsSolverBase /// number of degrees of freedom per reservoir element integer m_numDofPerResElement; + + /// minimum value of the scaling factor obtained by enforcing maxCompFracChange + real64 m_minScalingFactor; + + /// flag indicating whether local (cell-wise) chopping of negative compositions is allowed + integer m_allowCompDensChopping; }; } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp index 6a288bbd537..e0850cf43c9 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp @@ -209,93 +209,7 @@ void WellSolverBase::setupDofs( DomainPartition const & domain, DofManager::Connector::Node ); } -void WellSolverBase::setPerforationStatus( real64 const & time_n, DomainPartition & domain ) -{ - FunctionManager & functionManager = FunctionManager::getInstance(); - - // Set well element/perf status - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - ElementRegionManager & elemManager = mesh.getElemManager(); - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - WellControls & wellControls = getWellControls( subRegion ); - - // Set perforation status - - PerforationData & perforationData = *subRegion.getPerforationData(); - string_array const & perfStatusTableName = perforationData.getPerfStatusTableName(); - arrayView1d< integer > perfStatus = perforationData.getLocalPerfStatus(); - // for now set to open - for( integer i=0; i( perfStatusTableName[i] ); - perfStatus[i]=PerforationData::PerforationStatus::OPEN; - if( tableFunction->evaluate( &time_n ) < LvArray::NumericLimits< real64 >::epsilon ) - { - perfStatus[i]=PerforationData::PerforationStatus::CLOSED; - } - } - - array1d< localIndex > const perfWellElemIndex = perforationData.getField< fields::perforation::wellElementIndex >(); - // global index local elements (size == subregion.size) - arrayView1d< globalIndex const > globalWellElementIndex = subRegion.getGlobalWellElementIndex(); - - arrayView1d< integer const > const elemGhostRank = subRegion.ghostRank(); - array1d< integer > & currentStatus = subRegion.getWellElementStatus(); - // Local elements - array1d< integer > & localElemStatus = subRegion.getWellLocalElementStatus(); - - integer numLocalElements = subRegion.getNumLocalElements(); - array1d< integer > segStatus( numLocalElements ); - - // Local perforations - for( integer j = 0; j < perforationData.size(); j++ ) - { - localIndex const iwelem = perfWellElemIndex[j]; - if( elemGhostRank[iwelem] < 0 ) - { - if( perfStatus[j] ) - { - segStatus[iwelem] +=1; - } - } - } - // Broadcast segment status so all cores have same well status - subRegion.setElementStatus( segStatus ); - integer numOpenElements = 0; - array1d< integer > const & updatedStatus = subRegion.getWellElementStatus(); - for( integer i=0; i0 ? wellControls.setWellStatus( time_n, WellControls::Status::OPEN ) : wellControls.setWellStatus( time_n, WellControls::Status::CLOSED ); - - - // Set local well element status array - for( integer i=0; i const & localMatrix, arrayView1d< real64 > const & localRhs ) = 0; - virtual void assembleWellFluxTerms( real64 const & GEOS_UNUSED_PARAM( time ), - real64 const & GEOS_UNUSED_PARAM( dt ), - WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), - DofManager const & GEOS_UNUSED_PARAM( dofManager ), - CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), - arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) = 0; - - /** * @brief assembles the accumulation term for all the well elements @@ -284,68 +274,8 @@ class WellSolverBase : public WellControls DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) = 0; - /** - * @brief assembles the accumulation term for an individual well - * @param time_n time at the beginning of the time step - * @param dt the time step size - * @param subRegion the well subregion containing all the primary and dependent fields - * @param dofManager degree-of-freedom manager associated with the linear system - * @param matrix the system matrix - * @param rhs the system right-hand side vector - */ - virtual void assembleWellAccumulationTerms( real64 const & time, - real64 const & dt, - WellElementSubRegion & subRegion, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) = 0; - /** - * @brief assembles the constraint terms for an individual well - * @param time_n time at the beginning of the time step - * @param dt the time step size - * @param subRegion the well subregion containing all the primary and dependent fields - * @param dofManager degree-of-freedom manager associated with the linear system - * @param matrix the system matrix - * @param rhs the system right-hand side vector - */ - virtual void assembleWellConstraintTerms( real64 const & GEOS_UNUSED_PARAM( time ), - real64 const & GEOS_UNUSED_PARAM( dt ), - WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), - DofManager const & GEOS_UNUSED_PARAM( dofManager ), - CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), - arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) = 0; - /** - * @brief assembles the pressure relations at all connections between well elements except at - * the well head - * @param time_n time at the beginning of the time step - * @param dt the time step size - * @param domain the physical domain object - * @param dofManager degree-of-freedom manager associated with the linear system - * @param matrix the system matrix - * @param rhs the system right-hand side vector - */ - virtual void assemblePressureRelations( real64 const & time_n, - real64 const & dt, - DomainPartition const & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) = 0; - /** - * @brief assembles the pressure relations for individual well at all connections between well elements except at the well head - * @param time_n time at the beginning of the time step - * @param dt the time step size - * @param subRegion the well subregion containing all the primary and dependent fields - * @param dofManager degree-of-freedom manager associated with the linear system - * @param matrix the system matrix - * @param rhs the system right-hand side vector - */ - virtual void assembleWellPressureRelations ( real64 const & GEOS_UNUSED_PARAM( time ), - real64 const & GEOS_UNUSED_PARAM( dt ), - WellElementSubRegion const & GEOS_UNUSED_PARAM( subRegion ), - DofManager const & GEOS_UNUSED_PARAM( dofManager ), - CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), - arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) = 0; + /** * @brief Recompute all dependent quantities from primary variables (including constitutive @@ -366,7 +296,6 @@ class WellSolverBase : public WellControls * @param domain the domain containing the well manager to access individual wells */ virtual void initializeWells( DomainPartition & domain, real64 const & time_n ) = 0; - virtual void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) = 0; /** * @brief Recompute all dependent quantities from primary variables (including constitutive @@ -377,11 +306,6 @@ class WellSolverBase : public WellControls virtual real64 updateSubRegionState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) = 0; - virtual void computeWellPerforationRates( real64 const & GEOS_UNUSED_PARAM( time_n ), - real64 const & GEOS_UNUSED_PARAM( dt ), - ElementRegionManager const & GEOS_UNUSED_PARAM( elemManager ), - WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ) ){} - /** * @brief Recompute the perforation rates for all the wells * @param domain the domain containing the mesh and fields @@ -407,6 +331,8 @@ class WellSolverBase : public WellControls static constexpr char const * isThermalString() { return "isThermal"; } static constexpr char const * writeCSVFlagString() { return "writeCSV"; } static constexpr char const * timeStepFromTablesFlagString() { return "timeStepFromTables"; } + /// @return string for the targetRegions wrapper + static constexpr char const * targetRegionsString() { return "targetRegions"; } static constexpr char const * fluidNamesString() { return "fluidNames"; } }; @@ -442,8 +368,6 @@ class WellSolverBase : public WellControls real64 const & dt, DomainPartition & domain ) = 0; - virtual bool evaluateConstraints( real64 const & time_n, - WellElementSubRegion & subRegion ) = 0; /// name of the flow solver diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhasePerforationFluxKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhasePerforationFluxKernels.hpp index 559245cca72..3a9bbf94565 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhasePerforationFluxKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhasePerforationFluxKernels.hpp @@ -318,7 +318,7 @@ class PerforationFluxKernelFactory PerforationData * const perforationData, ElementSubRegionBase const & subRegion, constitutive::SingleFluidBase const & fluid, - ElementRegionManager & elemManager ) + ElementRegionManager const & elemManager ) { integer constexpr IS_THERMAL = 0; using kernelType = PerforationFluxKernel< IS_THERMAL >; @@ -514,7 +514,7 @@ class PerforationFluxKernelFactory PerforationData * const perforationData, ElementSubRegionBase const & subRegion, SingleFluidBase const & fluid, - ElementRegionManager & elemManager ) + ElementRegionManager const & elemManager ) { integer constexpr IS_THERMAL = 1; using kernelType = PerforationFluxKernel< IS_THERMAL >; diff --git a/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp b/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp index 17955899bf8..b8e162884c9 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp +++ b/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp @@ -148,7 +148,7 @@ initializePreSubGroups() CompositionalMultiphaseBase const * const flowSolver = this->flowSolver(); Base::wellSolver()->setFlowSolverName( flowSolver->getName() ); bool const useMassFlow = flowSolver->getReference< integer >( CompositionalMultiphaseBase::viewKeyStruct::useMassFlagString() ); - bool const useMassWell = Base::wellSolver()->template getReference< integer >( CompositionalMultiphaseWell::viewKeyStruct::useMassFlagString() ); + bool const useMassWell = Base::wellSolver()->template getReference< integer >( WellManager::viewKeyStruct::useMassFlagString() ); GEOS_THROW_IF( useMassFlow != useMassWell, GEOS_FMT( "{}: the input flag {} must be the same in the flow and well solvers, respectively '{}' and '{}'", this->getDataContext(), CompositionalMultiphaseBase::viewKeyStruct::useMassFlagString(), @@ -156,12 +156,27 @@ initializePreSubGroups() InputError, this->getDataContext(), Base::reservoirSolver()->getDataContext(), Base::wellSolver()->getDataContext() ); bool const isThermalFlow = flowSolver->getReference< integer >( CompositionalMultiphaseBase::viewKeyStruct::isThermalString() ); - bool const isThermalWell = Base::wellSolver()->template getReference< integer >( CompositionalMultiphaseWell::viewKeyStruct::isThermalString() ); + bool const isThermalWell = Base::wellSolver()->template getReference< integer >( WellManager::viewKeyStruct::isThermalString() ); GEOS_THROW_IF( isThermalFlow != isThermalWell, GEOS_FMT( "{}: the input flag {} must be the same in the flow and well solvers, respectively '{}' and '{}'", this->getDataContext(), CompositionalMultiphaseBase::viewKeyStruct::isThermalString(), Base::reservoirSolver()->getDataContext(), Base::wellSolver()->getDataContext() ), InputError, this->getDataContext(), Base::reservoirSolver()->getDataContext(), Base::wellSolver()->getDataContext() ); + DomainPartition & domain = this->template getGroupByPath< DomainPartition >( "/Problem/domain" ); + + this->template forDiscretizationOnMeshTargets<>( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + ElementRegionManager & elemManager = mesh.getElemManager(); + elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, + WellElementSubRegion const & subRegion ) + { + WellControls & wellControls = Base::wellSolver()->getWellControls( subRegion ); + wellControls.setFlowSolverName( flowSolver->getName() ); + + } ); + } ); } template< typename RESERVOIR_SOLVER > From c91c883b44dac1c01335451a01e6d5d07c5c49da Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Thu, 22 Jan 2026 12:02:15 -0800 Subject: [PATCH 53/71] blackoil case matches prev baseline code --- .../compositionalMultiphaseWell/bos.xml | 14 +++-- .../wells/CompositionalMultiphaseWell.cpp | 19 ++++--- .../wells/CompositionalMultiphaseWell.hpp | 20 +++---- .../fluidFlow/wells/SinglePhaseWell.cpp | 2 +- .../fluidFlow/wells/SinglePhaseWell.hpp | 2 +- .../fluidFlow/wells/WellControls.cpp | 57 +++++++++++++++---- .../fluidFlow/wells/WellControls.hpp | 1 + .../fluidFlow/wells/WellManager.cpp | 51 +++++++++++------ .../fluidFlow/wells/WellManager.hpp | 7 +++ 9 files changed, 122 insertions(+), 51 deletions(-) diff --git a/inputFiles/compositionalMultiphaseWell/bos.xml b/inputFiles/compositionalMultiphaseWell/bos.xml index dd692e88969..6a5a33071d9 100644 --- a/inputFiles/compositionalMultiphaseWell/bos.xml +++ b/inputFiles/compositionalMultiphaseWell/bos.xml @@ -4,7 +4,7 @@ + control="BHP" + useMass="1"> + nonWettingIntermediateRelPermTableNames="{ gasRelPermTable, oilRelPermTableForOG }"/> ( getFlowSolverName() ); + CompositionalMultiphaseBase const & flowSolver = getParent().getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); string_array const & targetRegionsNames = flowSolver.getTargetRegionNames(); auto const pos = std::find( targetRegionsNames.begin(), targetRegionsNames.end(), regionName ); GEOS_ERROR_IF( pos == targetRegionsNames.end(), @@ -413,8 +413,11 @@ void CompositionalMultiphaseWell::initializePostInitialConditionsPreSubGroups() void CompositionalMultiphaseWell::initializeWellPostInitialConditionsPreSubGroups( WellElementSubRegion & subRegion ) { - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + // set gravity coefficient + setGravCoef( subRegion, getParent().getParent().getReference< R1Tensor >( PhysicsSolverManager::viewKeyStruct::gravityVectorString() )); + // setup fluid model + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); constitutive::MultiFluidBase & fluid = subRegion.getConstitutiveModel< constitutive::MultiFluidBase >( fluidName ); fluid.setMassFlag( m_useMass ); createSeparator( subRegion ); @@ -557,6 +560,7 @@ void CompositionalMultiphaseWell::updateVolRatesForConstraint( WellElementSubReg currentMassRate = currentTotalRate; // Step 1.1: compute the inverse of the total density and derivatives massDensity = totalDens[iwelemRef][0]; + std::cout << "massDensity: " << massDensity << std::endl; real64 const totalDensInv = 1.0 / totalDens[iwelemRef][0]; // Step 1.2: divide the total mass/molar rate by the total density to get the total volumetric rate @@ -831,6 +835,7 @@ void CompositionalMultiphaseWell::updateSeparator( ElementRegionManager const & } else { + std::cout << "flashPressure: " << flashPressure << ", flashTemperature: " << flashTemperature << " " << compFrac[iwelemRef] << std::endl; fluidSeparatorWrapper.update( iwelemRef, 0, flashPressure, flashTemperature, compFrac[iwelemRef] ); } } ); @@ -906,9 +911,9 @@ real64 CompositionalMultiphaseWell::updateSubRegionState( ElementRegionManager c updateGlobalComponentFraction( subRegion ); // update densities, phase fractions, phase volume fractions - + std::cout << "Updating fluid model..." << std::endl; updateFluidModel( subRegion ); // Calculate fluid properties - + std::cout << "Updating separator..." << std::endl; updateSeparator( elemManager, subRegion ); // Calculate fluid properties at control conditions updateVolRatesForConstraint( subRegion ); // remove tjb ?? @@ -1501,7 +1506,7 @@ CompositionalMultiphaseWell::calculateWellResidualNorm( real64 const & time_n, } -void +real64 CompositionalMultiphaseWell::scalingForLocalSystemSolution( WellElementSubRegion & subRegion, DofManager const & dofManager, real64 & maxDeltaPres, @@ -1614,7 +1619,7 @@ CompositionalMultiphaseWell::scalingForLocalSystemSolution( WellElementSubRegion getName(), minTempScalingFactor ) ); } - + return LvArray::math::max( scalingFactor, m_minScalingFactor ); } real64 @@ -1788,7 +1793,7 @@ void CompositionalMultiphaseWell::computeWellPerforationRates( real64 const & ti GEOS_MARK_FUNCTION; GEOS_UNUSED_VAR( time_n ); - CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); + CompositionalMultiphaseBase const & flowSolver = getParent().getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); PerforationData * const perforationData = subRegion.getPerforationData(); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp index 265d55db0b1..d96bfcbe816 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp @@ -176,15 +176,15 @@ class CompositionalMultiphaseWell : public WellControls /** * @copydoc WellControls::scalingForSystemSolution() */ - void scalingForLocalSystemSolution ( WellElementSubRegion & subRegion, - DofManager const & dofManager, - real64 & maxDeltaPres, - real64 & maxDeltaCompDens, - real64 & maxDeltaTemp, - real64 & minPresScalingFactor, - real64 & minCompDensScalingFactor, - real64 & minTempScalingFactor, - arrayView1d< real64 const > const & localSolution ); + real64 scalingForLocalSystemSolution ( WellElementSubRegion & subRegion, + DofManager const & dofManager, + real64 & maxDeltaPres, + real64 & maxDeltaCompDens, + real64 & maxDeltaTemp, + real64 & minPresScalingFactor, + real64 & minCompDensScalingFactor, + real64 & minTempScalingFactor, + arrayView1d< real64 const > const & localSolution ); virtual real64 scalingForWellSystemSolution( WellElementSubRegion & subRegion, DofManager const & dofManager, @@ -316,7 +316,7 @@ class CompositionalMultiphaseWell : public WellControls struct viewKeyStruct : WellControls::viewKeyStruct { - static constexpr char const * dofFieldString() { return "compositionalWellVars"; } + static constexpr char const * dofFieldString() { return "wellVars"; } // inputs diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index 34eebf4550d..fc37b939e65 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -173,7 +173,7 @@ void SinglePhaseWell::initializeWellPostInitialConditionsPreSubGroups( WellEleme void SinglePhaseWell::initializePostInitialConditionsPreSubGroups() { //WellControl::initializePostInitialConditionsPreSubGroups(); - + } void SinglePhaseWell::postRestartInitialization( ) { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp index 2fa94d88ac0..a6a23e3cada 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp @@ -93,7 +93,7 @@ class SinglePhaseWell : public WellControls * @param time_n the current time */ virtual void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n )override; - + virtual void initializeWellPostInitialConditionsPreSubGroups( WellElementSubRegion & subRegion )override; /** * @brief Function to evaluate well constraints after applying the solution update diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index 2c408fa70ba..dd25978e683 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -23,8 +23,8 @@ #include "dataRepository/InputFlags.hpp" #include "functions/FunctionManager.hpp" #include "mesh/PerforationFields.hpp" - - +#include "fileIO/Outputs/OutputBase.hpp" +#include "physicsSolvers/fluidFlow/wells/WellSolverBaseFields.hpp" namespace geos { @@ -39,6 +39,8 @@ WellControls::WellControls( string const & name, Group * const parent ) m_numDofPerResElement( 0 ), m_isThermal( 0 ), m_keepVariablesConstantDuringInitStep( false ), + m_ratesOutputDir( joinPath( OutputBase::getOutputDirectory(), name + "_rates" ) ), + m_inputControl( Control::UNINITIALIZED ), m_currentControl( Control::UNINITIALIZED ), m_useSurfaceConditions( 0 ), @@ -136,12 +138,12 @@ WellControls::~WellControls() Group * WellControls::createChild( string const & childKey, string const & childName ) { - Group * baseChild = Group::createChild( childKey, childName ); - if( baseChild != nullptr ) - { - return baseChild; - } - GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); + //Group * baseChild = Group::createChild( childKey, childName ); + //if( baseChild != nullptr ) + //{ + // return baseChild; + //} + //GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); ////const auto childTypes = { viewKeyStruct::perforationString() }; //GEOS_ERROR_IF( childKey != viewKeyStruct::perforationString(), // CatalogInterface::unknownTypeError( childKey, getDataContext(), childTypes ) ); @@ -315,9 +317,7 @@ void WellControls::postInputInitialization() } void WellControls::postRestartInitialization( ) -{ - -} +{} void WellControls::setWellStatus( real64 const & currentTime, WellControls::Status status ) { m_wellStatus = status; @@ -482,6 +482,7 @@ real64 WellControls::getReferenceElevation() const } return getMaxBHPConstraint()->getReferenceElevation(); } + void WellControls::implicitStepSetup( real64 const & time_n, real64 const & GEOS_UNUSED_PARAM( dt ), ElementRegionManager & elemManager, @@ -554,4 +555,38 @@ void WellControls::setPerforationStatus( real64 const & time_n, WellElementSubRe } +void WellControls::setGravCoef( WellElementSubRegion & subRegion, R1Tensor const & gravVector ) +{ + PerforationData & perforationData = *subRegion.getPerforationData(); + + real64 const refElev = getReferenceElevation(); + + arrayView2d< real64 const > const wellElemLocation = subRegion.getElementCenter(); + arrayView1d< real64 > const wellElemGravCoef = subRegion.getField< fields::well::gravityCoefficient >(); + + arrayView2d< real64 const > const perfLocation = perforationData.getField< fields::perforation::location >(); + arrayView1d< real64 > const perfGravCoef = perforationData.getField< fields::well::gravityCoefficient >(); + + forAll< serialPolicy >( perforationData.size(), [=]( localIndex const iperf ) + { + // precompute the depth of the perforations + perfGravCoef[iperf] = LvArray::tensorOps::AiBi< 3 >( perfLocation[iperf], gravVector ); + } ); + + forAll< serialPolicy >( subRegion.size(), [=]( localIndex const iwelem ) + { + // precompute the depth of the well elements + wellElemGravCoef[iwelem] = LvArray::tensorOps::AiBi< 3 >( wellElemLocation[iwelem], gravVector ); + } ); + + forSubGroups< BHPConstraint >( [&]( auto & constraint ) + { + // set the reference well element where the BHP control is applied + real64 const refElev1 = constraint.getReferenceElevation(); + constraint.setReferenceGravityCoef( refElev1 * gravVector[2] ); + } ); + + // set the reference well element where the BHP control is applied + setReferenceGravityCoef( refElev * gravVector[2] ); // tjb remove +} } //namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp index 3fb393592d3..15ce367023f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp @@ -772,6 +772,7 @@ class WellControls : public dataRepository::Group //public PhysicsSolverBase /// ViewKey struct for the WellControls class viewKeysWellControls; void setPerforationStatus( real64 const & time_n, WellElementSubRegion & subRegion ); + void setGravCoef( WellElementSubRegion & subRegion, R1Tensor const & gravVector ); /** * @brief Set next time step based on a table function * @param[in] table the table function diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp index 043215670b9..ef2c0f29ff4 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp @@ -733,7 +733,7 @@ WellManager::calculateResidualNorm( real64 const & time_n, GEOS_MARK_FUNCTION; integer numNorm = 1; // mass balance - array1d< real64 > localResidualNorm; + array1d< real64 > localResidualNorm, wellResidalNorm; array1d< real64 > localResidualNormalizer; if( isThermal() ) @@ -741,6 +741,7 @@ WellManager::calculateResidualNorm( real64 const & time_n, numNorm = 2; // mass balance and energy balance } localResidualNorm.resize( numNorm ); + localResidualNormalizer.resize( numNorm ); @@ -765,12 +766,19 @@ WellManager::calculateResidualNorm( real64 const & time_n, // step 1: compute the norm in the subRegion if( true ) // tjb wellControls.isWellOpen( ) ) { - localResidualNorm = wellControls.calculateLocalWellResidualNorm( time_n, - dt, - m_nonlinearSolverParameters, - subRegion, - dofManager, - localRhs ); + wellResidalNorm = wellControls.calculateLocalWellResidualNorm( time_n, + dt, + m_nonlinearSolverParameters, + subRegion, + dofManager, + localRhs ); + for( integer i=0; i localResidualNorm[i] ) + { + localResidualNorm[i] = wellResidalNorm[i]; + } + } } else { @@ -818,12 +826,15 @@ WellManager::scalingForSystemSolution( DomainPartition & domain, string const wellDofKey = dofManager.getKey( wellElementDofName() ); real64 scalingFactor = 1.0; + real64 localScalingFactor = 1.0; if( isCompositional() ) { real64 maxDeltaPres = 0.0, maxDeltaCompDens = 0.0, maxDeltaTemp = 0.0; real64 minPresScalingFactor = 1.0, minCompDensScalingFactor = 1.0, minTempScalingFactor = 1.0; + real64 localMaxDeltaPres = 0.0, localMaxDeltaCompDens = 0.0, localMaxDeltaTemp = 0.0; + real64 localMinPresScalingFactor = 1.0, localMinCompDensScalingFactor = 1.0, localMinTempScalingFactor = 1.0; forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, @@ -837,16 +848,22 @@ WellManager::scalingForSystemSolution( DomainPartition & domain, { CompositionalMultiphaseWell * wellControls = dynamic_cast< CompositionalMultiphaseWell * >(&getWellControls ( subRegion )); - wellControls->scalingForLocalSystemSolution( subRegion, - dofManager, - maxDeltaPres, - maxDeltaCompDens, - maxDeltaTemp, - minPresScalingFactor, - minCompDensScalingFactor, - minTempScalingFactor, - localSolution ); - + localScalingFactor = wellControls->scalingForLocalSystemSolution( subRegion, + dofManager, + localMaxDeltaPres, + localMaxDeltaCompDens, + localMaxDeltaTemp, + localMinPresScalingFactor, + localMinCompDensScalingFactor, + localMinTempScalingFactor, + localSolution ); + maxDeltaPres = LvArray::math::max( localMaxDeltaPres, maxDeltaPres ); + maxDeltaCompDens = LvArray::math::max( localMaxDeltaCompDens, maxDeltaCompDens ); + maxDeltaTemp = LvArray::math::max( localMaxDeltaTemp, maxDeltaTemp ); + minPresScalingFactor = LvArray::math::min( localMinPresScalingFactor, minPresScalingFactor ); + minCompDensScalingFactor = LvArray::math::min( localMinCompDensScalingFactor, minCompDensScalingFactor ); + minTempScalingFactor = LvArray::math::min( localMinTempScalingFactor, minTempScalingFactor ); + scalingFactor = LvArray::math::min( localScalingFactor, scalingFactor ); } ); } ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp index 8b5e1d00307..66fe3b6b8cd 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp @@ -289,6 +289,13 @@ class WellManager : public PhysicsSolverBase real64 const & dt, DomainPartition & domain ) override; + virtual void applyBoundaryConditions( real64 const GEOS_UNUSED_PARAM( time_n ), + real64 const GEOS_UNUSED_PARAM( dt ), + DomainPartition & GEOS_UNUSED_PARAM( domain ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ), + CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), + arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) override {} + /** * @brief calculate the norm of the global system residual * @param time the time at the beginning of the step From 3454405120d97fde0f3fd75f25e8b196e6eb6d13 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Fri, 23 Jan 2026 12:08:44 -0800 Subject: [PATCH 54/71] compo input files to new schema, some || runs crash --- .../1D_100cells/1D_benchmark.xml | 33 +- .../soreideWhitson/1D_100cells/1D_smoke.xml | 33 +- .../class09_pb3_drainageOnly_direct_base.xml | 11 +- ...lass09_pb3_drainageOnly_iterative_base.xml | 25 +- .../class09_pb3_hystRelperm_direct_base.xml | 11 +- ...class09_pb3_hystRelperm_iterative_base.xml | 11 +- .../benchmarks/Egg/deadOilEgg_base_direct.xml | 101 +- .../Egg/deadOilEgg_base_iterative.xml | 101 +- .../black_oil_wells_saturated_3d.xml | 24 +- .../black_oil_wells_saturated_3d_stone2.xml | 24 +- .../black_oil_wells_unsaturated_3d.xml | 24 +- .../black_oil_wells_unsaturated_3d_stone2.xml | 24 +- .../compositional_multiphase_wells_1d.xml | 12 +- .../compositional_multiphase_wells_2d.xml | 16 +- .../dead_oil_wells_2d.xml | 32 +- .../dead_oil_wells_hybrid_2d.xml | 32 +- .../dome_kvalue_base.xml | 37 +- .../dome_soreide_whitson_base.xml | 37 +- .../isothm_mass_inj_table.xml | 11 +- .../isothm_vol_inj_table.xml | 11 +- .../resvol_constraint.xml | 19 +- .../simpleCo2InjTutorial_base.xml | 13 +- .../staged_perf_base.xml | 8 +- .../staircase_co2_wells_3d.xml | 21 +- .../staircase_co2_wells_hybrid_3d.xml | 24 +- .../PoroElastic_staircase_co2_3d_fim.xml | 21 +- ...oroElastic_staircase_co2_3d_sequential.xml | 21 +- ...roElastic_staircase_singlephase_3d_fim.xml | 12 +- ...ic_staircase_singlephase_3d_sequential.xml | 12 +- ...oromechanics_FaultModel_well_fim_smoke.xml | 13 +- ...oromechanics_FaultModel_well_seq_smoke.xml | 13 +- ...echanics_FaultModel_well_fim_new_smoke.xml | 12 +- ...oromechanics_FaultModel_well_seq_smoke.xml | 12 +- ...asePoromechanics_WellInFault_fim_smoke.xml | 17 +- ...asePoromechanics_WellInFault_seq_smoke.xml | 17 +- .../compressible_single_phase_wells_1d.xml | 12 +- ...sible_single_phase_wells_1d_skinFactor.xml | 12 +- ...pressible_single_phase_wells_hybrid_1d.xml | 12 +- .../incompressible_single_phase_wells_2d.xml | 16 +- ...pressible_single_phase_wells_hybrid_2d.xml | 16 +- .../singlePhaseWell/perf_status_test.xml | 16 +- .../staircase_single_phase_wells_3d.xml | 12 +- ...staircase_single_phase_wells_hybrid_3d.xml | 12 +- .../wells/CompositionalMultiphaseWell.cpp | 18 +- .../wells/CompositionalMultiphaseWell.hpp | 2 +- .../fluidFlow/wells/SinglePhaseWell.cpp | 46 +- .../fluidFlow/wells/WellControls.cpp | 44 +- .../fluidFlow/wells/WellControls.hpp | 11 +- .../fluidFlow/wells/WellManager.cpp | 125 +-- .../fluidFlow/wells/WellManager.hpp | 18 +- src/coreComponents/schema/schema.xsd | 955 +++++++++--------- src/coreComponents/schema/schema.xsd.other | 119 +-- 52 files changed, 1253 insertions(+), 1038 deletions(-) diff --git a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml index 1218d8156a2..cc7e0796fa3 100644 --- a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml +++ b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml @@ -31,15 +31,13 @@ temperature="349.15" useMass="0"/> - - + control="totalVolRate" + maxRelativePressureChange="0.5" + maxCompFractionChange="0.5" + useMass="0"> @@ -60,8 +61,8 @@ constraintScheduleTableName="WATER.INJECTOR.RATE" injectionStream="{ 0.0, 0.0, 1.0 }" injectionTemperature="349.15"/> - - + + control="totalVolRate" + maxRelativePressureChange="0.5" + maxCompFractionChange="0.5" + useMass="0"> @@ -82,15 +86,18 @@ constraintScheduleTableName="GAS.INJECTOR.RATE" injectionStream="{ 0.85, 0.15, 0.00 }" injectionTemperature="349.15"/> - - + + control="BHP" + maxRelativePressureChange="0.5" + maxCompFractionChange="0.5" + useMass="0"> - - + + diff --git a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml index 3e4fe211b1b..322444e025d 100644 --- a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml +++ b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_smoke.xml @@ -31,15 +31,13 @@ temperature="349.15" useMass="0"/> - - + control="totalVolRate" + maxRelativePressureChange="0.5" + maxCompFractionChange="0.5" + useMass="0"> - - + + control="totalVolRate" + maxRelativePressureChange="0.5" + maxCompFractionChange="0.5" + useMass="0"> - - + + control="BHP" + maxRelativePressureChange="0.5" + maxCompFractionChange="0.5" + useMass="0"> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_direct_base.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_direct_base.xml index 4d4ff61234c..01804189fd8 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_direct_base.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_direct_base.xml @@ -25,19 +25,20 @@ logLevel="1" useMass="1"/> - - + control="totalVolRate" + useMass="1"> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_iterative_base.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_iterative_base.xml index e585c6e4238..fe5f4272ad2 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_iterative_base.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_drainageOnly_iterative_base.xml @@ -28,12 +28,12 @@ logLevel="1" useMass="1"/> - - + control="totalVolRate" + useMass="1"> - - + + control="massRate" + useMass="1"> - - + + control="massRate" + useMass="1"> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_direct_base.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_direct_base.xml index 83ca125931e..01e328f6cfa 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_direct_base.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_direct_base.xml @@ -25,19 +25,20 @@ logLevel="1" useMass="1"/> - - + control="totalVolRate" + useMass="1"> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_iterative_base.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_iterative_base.xml index 6067d36b757..b71cf698726 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_iterative_base.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Class09Pb3/class09_pb3_hystRelperm_iterative_base.xml @@ -28,12 +28,12 @@ logLevel="1" useMass="1"/> - - + control="totalVolRate" + useMass="1"> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml index 742d818218b..93fe91dcc44 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml @@ -33,16 +33,17 @@ logLevel="1" useMass="1"/> - - + control="BHP" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="BHP" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="BHP" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="BHP" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.5" + useMass="1"> - - + + - - + control="BHP" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="BHP" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="BHP" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="BHP" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.5" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.5" + useMass="1"> - - + + - - + control="BHP" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1" + useMass="1"> - - + + control="BHP" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1" + useMass="1"> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml index 5df4a8cf991..8ae05610077 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml @@ -27,17 +27,18 @@ temperature="297.15" useMass="1"/> - - + control="BHP" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1" + useMass="1"> - - + + control="BHP" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1" + useMass="1"> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml index b2e5a4c7d91..a964a1ccd88 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml @@ -27,17 +27,18 @@ temperature="297.15" useMass="1"/> - - + control="BHP" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1" + useMass="1"> - - + + control="BHP" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1" + useMass="1"> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml index 464449a53f4..f8779107119 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml @@ -27,17 +27,18 @@ temperature="297.15" useMass="1"/> - - + control="BHP" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1" + useMass="1"> - - + + control="BHP" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1" + useMass="1"> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_1d.xml b/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_1d.xml index 2ba87aa5909..0869a727917 100644 --- a/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_1d.xml +++ b/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_1d.xml @@ -23,11 +23,11 @@ targetRegions="{ Region1 }" temperature="297.15"/> - - @@ -39,8 +39,8 @@ name="minbhp" targetBHP="4e6" referenceElevation="2"/> - - + @@ -53,8 +53,8 @@ volumeRate="1e-7" injectionStream="{ 0.1, 0.1, 0.1, 0.7 }" injectionTemperature="297.15"/> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_2d.xml b/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_2d.xml index 8217c4275f6..7fcaafb1102 100644 --- a/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_2d.xml +++ b/inputFiles/compositionalMultiphaseWell/compositional_multiphase_wells_2d.xml @@ -23,11 +23,11 @@ targetRegions="{ Region1 }" temperature="297.15"/> - - @@ -39,8 +39,8 @@ name="minbhp" targetBHP="4e6" referenceElevation="0.5"/> - - + @@ -52,8 +52,8 @@ name="minbhp" targetBHP="2e6" referenceElevation="0.5"/> - - + @@ -66,8 +66,8 @@ volumeRate="5e-7" injectionStream="{ 0.1, 0.1, 0.1, 0.7 }" injectionTemperature="297.15"/> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/dead_oil_wells_2d.xml b/inputFiles/compositionalMultiphaseWell/dead_oil_wells_2d.xml index db72b99731a..4b9ac35ea83 100644 --- a/inputFiles/compositionalMultiphaseWell/dead_oil_wells_2d.xml +++ b/inputFiles/compositionalMultiphaseWell/dead_oil_wells_2d.xml @@ -24,19 +24,19 @@ targetRegions="{ Region1 }" temperature="297.15"/> - - + + control="BHP" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1"> - - + + control="phaseVolRate" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1"> - - + + control="totalVolRate" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1"> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/dead_oil_wells_hybrid_2d.xml b/inputFiles/compositionalMultiphaseWell/dead_oil_wells_hybrid_2d.xml index 6758a80ea87..5b8123e4d27 100644 --- a/inputFiles/compositionalMultiphaseWell/dead_oil_wells_hybrid_2d.xml +++ b/inputFiles/compositionalMultiphaseWell/dead_oil_wells_hybrid_2d.xml @@ -23,19 +23,19 @@ targetRegions="{ Region1 }" temperature="297.15"/> - - + + control="BHP" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1"> - - + + control="BHP" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1"> - - + + control="totalVolRate" + maxRelativePressureChange="0.1" + maxCompFractionChange="0.1"> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/dome_kvalue_base.xml b/inputFiles/compositionalMultiphaseWell/dome_kvalue_base.xml index ab90d4d13c0..6de3051e122 100644 --- a/inputFiles/compositionalMultiphaseWell/dome_kvalue_base.xml +++ b/inputFiles/compositionalMultiphaseWell/dome_kvalue_base.xml @@ -42,15 +42,12 @@ solutionChangeScalingFactor="1" useMass="0"/> - - + logLevel="2" + maxRelativePressureChange="0.5" + maxCompFractionChange="0.5" + useMass="0" + writeCSV="1"> - - + + logLevel="2" + maxRelativePressureChange="0.5" + maxCompFractionChange="0.5" + useMass="0" + writeCSV="1"> - - + + logLevel="2" + maxRelativePressureChange="0.5" + maxCompFractionChange="0.5" + useMass="0" + writeCSV="1"> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/dome_soreide_whitson_base.xml b/inputFiles/compositionalMultiphaseWell/dome_soreide_whitson_base.xml index e5f85ebfbdd..d69956ea1de 100644 --- a/inputFiles/compositionalMultiphaseWell/dome_soreide_whitson_base.xml +++ b/inputFiles/compositionalMultiphaseWell/dome_soreide_whitson_base.xml @@ -42,15 +42,12 @@ solutionChangeScalingFactor="1" useMass="0"/> - - + logLevel="2" + maxRelativePressureChange="0.5" + maxCompFractionChange="0.5" + useMass="0" + writeCSV="1"> - - + + logLevel="2" + maxRelativePressureChange="0.5" + maxCompFractionChange="0.5" + useMass="0" + writeCSV="1"> - - + + logLevel="2" + maxRelativePressureChange="0.5" + maxCompFractionChange="0.5" + useMass="0" + writeCSV="1"> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/isothm_mass_inj_table.xml b/inputFiles/compositionalMultiphaseWell/isothm_mass_inj_table.xml index cf1631e6f94..9ecff209034 100644 --- a/inputFiles/compositionalMultiphaseWell/isothm_mass_inj_table.xml +++ b/inputFiles/compositionalMultiphaseWell/isothm_mass_inj_table.xml @@ -31,12 +31,12 @@ maxCompFractionChange="0.5" targetRegions="{ region }"/> - - + control="massRate" + useMass="1"> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml b/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml index 7c198945edd..1e191175e19 100644 --- a/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml +++ b/inputFiles/compositionalMultiphaseWell/isothm_vol_inj_table.xml @@ -31,12 +31,12 @@ maxCompFractionChange="0.5" targetRegions="{ region }"/> - - + control="totalVolRate" + useMass="1"> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/resvol_constraint.xml b/inputFiles/compositionalMultiphaseWell/resvol_constraint.xml index cab0d2ed29d..134b8a44552 100644 --- a/inputFiles/compositionalMultiphaseWell/resvol_constraint.xml +++ b/inputFiles/compositionalMultiphaseWell/resvol_constraint.xml @@ -23,16 +23,16 @@ targetRegions="{ Region1 }" temperature="297.15"/> - - + referenceReservoirRegion="Region1" + writeCSV="1"> - - + + referenceReservoirRegion="Region1" + writeCSV="1"> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/simpleCo2InjTutorial_base.xml b/inputFiles/compositionalMultiphaseWell/simpleCo2InjTutorial_base.xml index 5d4f887ad1e..d77a12e5cb5 100644 --- a/inputFiles/compositionalMultiphaseWell/simpleCo2InjTutorial_base.xml +++ b/inputFiles/compositionalMultiphaseWell/simpleCo2InjTutorial_base.xml @@ -29,20 +29,21 @@ logLevel="1" useMass="1"/> - - + control="totalVolRate" + maxCompFractionChange="0.2" + useMass="1"> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/staged_perf_base.xml b/inputFiles/compositionalMultiphaseWell/staged_perf_base.xml index 9e87e03c62f..d6359b2765e 100644 --- a/inputFiles/compositionalMultiphaseWell/staged_perf_base.xml +++ b/inputFiles/compositionalMultiphaseWell/staged_perf_base.xml @@ -24,11 +24,11 @@ targetRegions="{ reservoir }" temperature="297.15"/> - - @@ -40,8 +40,8 @@ name="minbhp" targetBHP="4e6" referenceElevation="0.5"/> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_3d.xml b/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_3d.xml index ad4a7cc4368..db9b88c034e 100644 --- a/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_3d.xml +++ b/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_3d.xml @@ -25,17 +25,18 @@ maxCompFractionChange="0.2" useMass="1"/> - - + control="phaseVolRate" + maxCompFractionChange="0.2" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.2" + useMass="1"> - - + + diff --git a/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml b/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml index f5d6b2a7340..3f398adb118 100644 --- a/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml +++ b/inputFiles/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml @@ -28,17 +28,18 @@ maxRelativePressureChange="0.2" useMass="1"/> - - + control="BHP" + maxRelativePressureChange="0.2" + maxCompFractionChange="0.2" + useMass="1"> - - + + control="totalVolRate" + maxRelativePressureChange="0.2" + maxCompFractionChange="0.2" + useMass="1"> - - + + diff --git a/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_fim.xml b/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_fim.xml index 5e1a987f1cc..77dfa798145 100644 --- a/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_fim.xml +++ b/inputFiles/poromechanics/PoroElastic_staircase_co2_3d_fim.xml @@ -46,17 +46,18 @@ temperature="300" useMass="1"/> - - + control="BHP" + maxCompFractionChange="0.2" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.2" + useMass="1"> - - + + - - + control="BHP" + maxCompFractionChange="0.2" + useMass="1"> - - + + control="totalVolRate" + maxCompFractionChange="0.2" + useMass="1"> - - + + - - - - + - - + + - - - - + - - + + - - + logLevel="2" + useMass="1" + writeCSV="1"> - - + + diff --git a/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_seq_smoke.xml b/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_seq_smoke.xml index 5557c612313..4a30e02941e 100644 --- a/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_seq_smoke.xml +++ b/inputFiles/poromechanicsFractures/multiphasePoromechanics_FaultModel_well_seq_smoke.xml @@ -58,13 +58,12 @@ targetRegions="{ Region, Fault }" temperature="368.15"/> - - + logLevel="2" + useMass="1" + writeCSV="1"> - - + + diff --git a/inputFiles/poromechanicsFractures/singlePhasePoromechanics_FaultModel_well_fim_new_smoke.xml b/inputFiles/poromechanicsFractures/singlePhasePoromechanics_FaultModel_well_fim_new_smoke.xml index 369356badf7..72aad6f89b6 100644 --- a/inputFiles/poromechanicsFractures/singlePhasePoromechanics_FaultModel_well_fim_new_smoke.xml +++ b/inputFiles/poromechanicsFractures/singlePhasePoromechanics_FaultModel_well_fim_new_smoke.xml @@ -46,11 +46,11 @@ discretization="singlePhaseTPFA" targetRegions="{ Region, Fault }"/> - - - - + - - + + diff --git a/inputFiles/poromechanicsFractures/singlePhasePoromechanics_FaultModel_well_seq_smoke.xml b/inputFiles/poromechanicsFractures/singlePhasePoromechanics_FaultModel_well_seq_smoke.xml index 61c4951ba03..25fdb7ac680 100644 --- a/inputFiles/poromechanicsFractures/singlePhasePoromechanics_FaultModel_well_seq_smoke.xml +++ b/inputFiles/poromechanicsFractures/singlePhasePoromechanics_FaultModel_well_seq_smoke.xml @@ -51,11 +51,11 @@ discretization="singlePhaseTPFA" targetRegions="{ Region, Fault }"/> - - - - + - - + + diff --git a/inputFiles/poromechanicsFractures/singlePhasePoromechanics_WellInFault_fim_smoke.xml b/inputFiles/poromechanicsFractures/singlePhasePoromechanics_WellInFault_fim_smoke.xml index b9dd3feaa93..b40822f5011 100644 --- a/inputFiles/poromechanicsFractures/singlePhasePoromechanics_WellInFault_fim_smoke.xml +++ b/inputFiles/poromechanicsFractures/singlePhasePoromechanics_WellInFault_fim_smoke.xml @@ -2,7 +2,8 @@ - + + directParallel="1"/> - - - - + - - + + diff --git a/inputFiles/poromechanicsFractures/singlePhasePoromechanics_WellInFault_seq_smoke.xml b/inputFiles/poromechanicsFractures/singlePhasePoromechanics_WellInFault_seq_smoke.xml index 5f146390a0c..b0f284936a6 100644 --- a/inputFiles/poromechanicsFractures/singlePhasePoromechanics_WellInFault_seq_smoke.xml +++ b/inputFiles/poromechanicsFractures/singlePhasePoromechanics_WellInFault_seq_smoke.xml @@ -2,7 +2,8 @@ - + + directParallel="1"/> - - - - + - - + + diff --git a/inputFiles/singlePhaseWell/compressible_single_phase_wells_1d.xml b/inputFiles/singlePhaseWell/compressible_single_phase_wells_1d.xml index bd55d92c512..0fe903b3199 100644 --- a/inputFiles/singlePhaseWell/compressible_single_phase_wells_1d.xml +++ b/inputFiles/singlePhaseWell/compressible_single_phase_wells_1d.xml @@ -20,11 +20,11 @@ discretization="singlePhaseTPFA" targetRegions="{ Region1 }"/> - - @@ -35,8 +35,8 @@ - - + @@ -47,8 +47,8 @@ - - + + diff --git a/inputFiles/singlePhaseWell/compressible_single_phase_wells_1d_skinFactor.xml b/inputFiles/singlePhaseWell/compressible_single_phase_wells_1d_skinFactor.xml index 9bdf4ec4843..86513856eeb 100644 --- a/inputFiles/singlePhaseWell/compressible_single_phase_wells_1d_skinFactor.xml +++ b/inputFiles/singlePhaseWell/compressible_single_phase_wells_1d_skinFactor.xml @@ -20,11 +20,11 @@ discretization="singlePhaseTPFA" targetRegions="{ Region1 }"/> - - @@ -35,8 +35,8 @@ - - + @@ -47,8 +47,8 @@ - - + + diff --git a/inputFiles/singlePhaseWell/compressible_single_phase_wells_hybrid_1d.xml b/inputFiles/singlePhaseWell/compressible_single_phase_wells_hybrid_1d.xml index c57a6031018..5b5cc462b41 100644 --- a/inputFiles/singlePhaseWell/compressible_single_phase_wells_hybrid_1d.xml +++ b/inputFiles/singlePhaseWell/compressible_single_phase_wells_hybrid_1d.xml @@ -21,11 +21,11 @@ discretization="singlePhaseHybridMimetic" targetRegions="{ Region1 }"/> - - @@ -36,8 +36,8 @@ - - + @@ -48,8 +48,8 @@ - - + + diff --git a/inputFiles/singlePhaseWell/incompressible_single_phase_wells_2d.xml b/inputFiles/singlePhaseWell/incompressible_single_phase_wells_2d.xml index 232cb196567..9f5f0a50843 100644 --- a/inputFiles/singlePhaseWell/incompressible_single_phase_wells_2d.xml +++ b/inputFiles/singlePhaseWell/incompressible_single_phase_wells_2d.xml @@ -20,11 +20,11 @@ discretization="singlePhaseTPFA" targetRegions="{ Region1 }"/> - - @@ -35,8 +35,8 @@ - - + @@ -47,8 +47,8 @@ - - + - - + + diff --git a/inputFiles/singlePhaseWell/incompressible_single_phase_wells_hybrid_2d.xml b/inputFiles/singlePhaseWell/incompressible_single_phase_wells_hybrid_2d.xml index 911c36553c7..28a95e82f30 100644 --- a/inputFiles/singlePhaseWell/incompressible_single_phase_wells_hybrid_2d.xml +++ b/inputFiles/singlePhaseWell/incompressible_single_phase_wells_hybrid_2d.xml @@ -21,11 +21,11 @@ discretization="singlePhaseHybridMimetic" targetRegions="{ Region1 }"/> - - @@ -36,8 +36,8 @@ - - + @@ -48,8 +48,8 @@ - - + @@ -60,8 +60,8 @@ - - + + diff --git a/inputFiles/singlePhaseWell/perf_status_test.xml b/inputFiles/singlePhaseWell/perf_status_test.xml index 1a0d21fbd0d..518652a9acc 100644 --- a/inputFiles/singlePhaseWell/perf_status_test.xml +++ b/inputFiles/singlePhaseWell/perf_status_test.xml @@ -21,11 +21,11 @@ discretization="singlePhaseTPFA" targetRegions="{ Region1 }"/> - - @@ -36,8 +36,8 @@ - - + @@ -48,8 +48,8 @@ - - + - - + + diff --git a/inputFiles/singlePhaseWell/staircase_single_phase_wells_3d.xml b/inputFiles/singlePhaseWell/staircase_single_phase_wells_3d.xml index c8cb5ca9a9f..55da1048afe 100644 --- a/inputFiles/singlePhaseWell/staircase_single_phase_wells_3d.xml +++ b/inputFiles/singlePhaseWell/staircase_single_phase_wells_3d.xml @@ -20,11 +20,11 @@ discretization="singlePhaseTPFA" targetRegions="{ Channel }"/> - - @@ -35,8 +35,8 @@ - - + @@ -47,8 +47,8 @@ - - + + diff --git a/inputFiles/singlePhaseWell/staircase_single_phase_wells_hybrid_3d.xml b/inputFiles/singlePhaseWell/staircase_single_phase_wells_hybrid_3d.xml index c9c874c8a07..256250d8cc7 100644 --- a/inputFiles/singlePhaseWell/staircase_single_phase_wells_hybrid_3d.xml +++ b/inputFiles/singlePhaseWell/staircase_single_phase_wells_hybrid_3d.xml @@ -21,11 +21,11 @@ discretization="singlePhaseHybridMimetic" targetRegions="{ Channel }"/> - - @@ -36,8 +36,8 @@ - - + - - + + diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 16674e3ae96..40abf3e1c0d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -151,7 +151,7 @@ void CompositionalMultiphaseWell::setConstitutiveNames( ElementSubRegionBase & s } void CompositionalMultiphaseWell::registerWellDataOnMesh( WellElementSubRegion & subRegion ) { - // WellControls::registerDataOnMesh( meshBodies ); replaced by following 2 lines + WellControls::registerWellDataOnMesh( subRegion ); setConstitutiveNames ( subRegion ); DomainPartition const & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); @@ -560,7 +560,6 @@ void CompositionalMultiphaseWell::updateVolRatesForConstraint( WellElementSubReg currentMassRate = currentTotalRate; // Step 1.1: compute the inverse of the total density and derivatives massDensity = totalDens[iwelemRef][0]; - std::cout << "massDensity: " << massDensity << std::endl; real64 const totalDensInv = 1.0 / totalDens[iwelemRef][0]; // Step 1.2: divide the total mass/molar rate by the total density to get the total volumetric rate @@ -835,7 +834,6 @@ void CompositionalMultiphaseWell::updateSeparator( ElementRegionManager const & } else { - std::cout << "flashPressure: " << flashPressure << ", flashTemperature: " << flashTemperature << " " << compFrac[iwelemRef] << std::endl; fluidSeparatorWrapper.update( iwelemRef, 0, flashPressure, flashTemperature, compFrac[iwelemRef] ); } } ); @@ -911,9 +909,9 @@ real64 CompositionalMultiphaseWell::updateSubRegionState( ElementRegionManager c updateGlobalComponentFraction( subRegion ); // update densities, phase fractions, phase volume fractions - std::cout << "Updating fluid model..." << std::endl; + updateFluidModel( subRegion ); // Calculate fluid properties - std::cout << "Updating separator..." << std::endl; + updateSeparator( elemManager, subRegion ); // Calculate fluid properties at control conditions updateVolRatesForConstraint( subRegion ); // remove tjb ?? @@ -1456,13 +1454,13 @@ CompositionalMultiphaseWell::calculateWellResidualNorm( real64 const & time_n, localResidualNormalizer.resize( numNorm ); - globalIndex const rankOffset = dofManager.rankOffset(); + //globalIndex const rankOffset = dofManager.rankOffset(); string const wellDofKey = dofManager.getKey( wellElementDofName() ); - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); + //string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + //MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); if( isWellOpen( ) ) { @@ -1793,7 +1791,7 @@ void CompositionalMultiphaseWell::computeWellPerforationRates( real64 const & ti GEOS_MARK_FUNCTION; GEOS_UNUSED_VAR( time_n ); - CompositionalMultiphaseBase const & flowSolver = getParent().getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); + //CompositionalMultiphaseBase const & flowSolver = getParent().getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); PerforationData * const perforationData = subRegion.getPerforationData(); @@ -1903,7 +1901,7 @@ CompositionalMultiphaseWell::applyWellSystemSolution( DofManager const & dofMana chopNegativeDensities( subRegion ); } #endif - + std::cout << getTargetRegionNames()[0] << " Well after applyWellSystemSolution: " << std::endl; // synchronize FieldIdentifiers fieldsToBeSync; if( isThermal() ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp index d96bfcbe816..495ba0908d5 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp @@ -74,7 +74,7 @@ class CompositionalMultiphaseWell : public WellControls virtual ~CompositionalMultiphaseWell() override = default; - void registerWellDataOnMesh( WellElementSubRegion & subRegion ) override; + virtual void registerWellDataOnMesh( WellElementSubRegion & subRegion ) override; /** * @defgroup WellManager Interface Functions * diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index fc37b939e65..4361f20d1b9 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -69,21 +69,30 @@ SinglePhaseWell::SinglePhaseWell( const string & name, void SinglePhaseWell::registerWellDataOnMesh( WellElementSubRegion & subRegion ) { -/// WellControls::registerDataOnMesh( meshBodies ); replaced by following 2 lines + WellControls::registerDataOnMesh( subRegion ); setConstitutiveNames ( subRegion ); - DomainPartition const & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); - ConstitutiveManager const & cm = domain.getConstitutiveManager(); + //DomainPartition const & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); + //ConstitutiveManager const & cm = domain.getConstitutiveManager(); if( m_referenceFluidModelName.empty() ) { - m_referenceFluidModelName = getConstitutiveName< MultiFluidBase >( subRegion ); + m_referenceFluidModelName = getConstitutiveName< SingleFluidBase >( subRegion ); } + subRegion.registerField< well::pressure >( getName() ); + subRegion.registerField< well::pressure_n >( getName() ); + subRegion.registerField< well::temperature >( getName() ); + if( isThermal() ) + { + subRegion.registerField< well::temperature_n >( getName() ); + } subRegion.registerField< well::connectionRate_n >( getName() ); subRegion.registerField< well::connectionRate >( getName() ); - + subRegion.registerField< well::gravityCoefficient >( getName() ); PerforationData & perforationData = *subRegion.getPerforationData(); + perforationData.registerField< well::gravityCoefficient >( getName() ); + perforationData.registerField< well::perforationRate >( getName() ); perforationData.registerField< well::dPerforationRate >( getName() ). reference().resizeDimension< 1, 2 >( 2, 2 ); @@ -92,6 +101,7 @@ void SinglePhaseWell::registerWellDataOnMesh( WellElementSubRegion & subRegion ) perforationData.registerField< well::energyPerforationFlux >( getName() ); perforationData.registerField< well::dEnergyPerforationFlux >( getName() ). reference().resizeDimension< 1, 2 >( 2, 2 ); + perforationData.registerField< well::gravityCoefficient >( getName() ); } @@ -137,7 +147,7 @@ void SinglePhaseWell::validateWellConstraints( real64 const & time_n, WellElementSubRegion const & subRegion ) { GEOS_UNUSED_VAR( time_n ); // tjb this will be needed with validation against tables - + GEOS_UNUSED_VAR( subRegion ); if( useSurfaceConditions() ) { bool useSeg = getReferenceReservoirRegion().empty(); @@ -164,20 +174,21 @@ void SinglePhaseWell::validateWellConstraints( real64 const & time_n, void SinglePhaseWell::initializeWellPostInitialConditionsPreSubGroups( WellElementSubRegion & subRegion ) { - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - constitutive::SingleFluidBase & fluid = subRegion.getConstitutiveModel< constitutive::SingleFluidBase >( fluidName ); + // set gravity coefficient + setGravCoef( subRegion, getParent().getParent().getReference< R1Tensor >( PhysicsSolverManager::viewKeyStruct::gravityVectorString() )); + // setup fluid model + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + constitutive::SingleFluidBase & fluid = subRegion.getConstitutiveModel< constitutive::SingleFluidBase >( fluidName ); createSeparator( subRegion ); } void SinglePhaseWell::initializePostInitialConditionsPreSubGroups() { - //WellControl::initializePostInitialConditionsPreSubGroups(); - + WellControls::initializePostInitialConditionsPreSubGroups(); } void SinglePhaseWell::postRestartInitialization( ) { - // setup fluid separator constitutive::SingleFluidBase & fluidSeparator = getSingleFluidSeparator(); fluidSeparator.allocateConstitutiveData( *this, 1 ); @@ -512,12 +523,9 @@ void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh } ); } } - - // TODO: change the way we access the flowSolver here - SinglePhaseBase const & flowSolver = getParent().getGroup< SinglePhaseBase >( getFlowSolverName() ); - - PresTempInitializationKernel::SinglePhaseFlowAccessors resSinglePhaseFlowAccessors( elemManager, flowSolver.getName() ); - PresTempInitializationKernel::SingleFluidAccessors resSingleFluidAccessors( elemManager, flowSolver.getName() ); + + PresTempInitializationKernel::SinglePhaseFlowAccessors resSinglePhaseFlowAccessors( elemManager, getFlowSolverName()); + PresTempInitializationKernel::SingleFluidAccessors resSingleFluidAccessors( elemManager,getFlowSolverName() ); // 1) Loop over all perforations to compute an average density // 2) Initialize the reference pressure @@ -1078,7 +1086,7 @@ SinglePhaseWell::calculateWellResidualNorm( real64 const & time_n, localResidualNormalizer.resize( numNorm ); - globalIndex const rankOffset = dofManager.rankOffset(); + //globalIndex const rankOffset = dofManager.rankOffset(); string const wellDofKey = dofManager.getKey( wellElementDofName() ); if( isWellOpen() ) @@ -1318,7 +1326,7 @@ void SinglePhaseWell::printRates( real64 const & time_n, WellElementSubRegion const & subRegion ) { - + GEOS_UNUSED_VAR( dt );// FIX THIS tjb // the rank that owns the reference well element is responsible for the calculations below. if( !subRegion.isLocallyOwned() ) { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index dd25978e683..7099c06bdcc 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -25,6 +25,7 @@ #include "mesh/PerforationFields.hpp" #include "fileIO/Outputs/OutputBase.hpp" #include "physicsSolvers/fluidFlow/wells/WellSolverBaseFields.hpp" +#include "functions/FunctionManager.hpp" namespace geos { @@ -39,8 +40,8 @@ WellControls::WellControls( string const & name, Group * const parent ) m_numDofPerResElement( 0 ), m_isThermal( 0 ), m_keepVariablesConstantDuringInitStep( false ), - m_ratesOutputDir( joinPath( OutputBase::getOutputDirectory(), name + "_rates" ) ), - + //m_ratesOutputDir( joinPath( OutputBase::getOutputDirectory(), "_rates" ) ), + m_ratesOutputDir( joinPath( OutputBase::getOutputDirectory(), parent->getName() + "_rates" ) ), m_inputControl( Control::UNINITIALIZED ), m_currentControl( Control::UNINITIALIZED ), m_useSurfaceConditions( 0 ), @@ -121,6 +122,7 @@ WellControls::WellControls( string const & name, Group * const parent ) " - Injector pressure at reference depth initialized as: (1+initialPressureCoefficient)*reservoirPressureAtClosestPerforation + density*g*( zRef - zPerf ) \n" " - Producer pressure at reference depth initialized as: (1-initialPressureCoefficient)*reservoirPressureAtClosestPerforation + density*g*( zRef - zPerf ) " ); +#if 0 registerWrapper( viewKeyStruct::targetRegionsString(), &m_targetRegionNames ). setRTTypeName( rtTypes::CustomTypes::groupNameRefArray ). setInputFlag( InputFlags::REQUIRED ). @@ -128,7 +130,7 @@ WellControls::WellControls( string const & name, Group * const parent ) "the solver will be applied to these regions, only that allocation will occur such that the " "solver may be applied to these regions. The decision about what regions this solver will be" "applied to rests in the EventManager." ); - +#endif addLogLevel< logInfo::WellControl >(); } @@ -239,7 +241,14 @@ TableFunction * createWellTable( string const & tableName, } } - +void WellControls::registerWellDataOnMesh( WellElementSubRegion & subRegion ) +{ + std::string const & regionName = subRegion.getName(); + std::string addrWithMask( regionName ); + std::size_t pos = addrWithMask.find( "UniqueSubRegion" ); + std::string addr = addrWithMask.substr( 0, pos ); + m_targetRegionNames.push_back( addr ); +} void WellControls::postInputInitialization() { Group::postInputInitialization(); @@ -354,7 +363,32 @@ void WellControls::setWellStatus( real64 const & currentTime, WellControls::Stat } } } +real64 WellControls::setNextDt( real64 const & currentTime, + real64 const & currentDt, + WellElementSubRegion & subRegion ) +{ + real64 nextDt = currentDt; + real64 nextDt_perf=nextDt; + // Find min dt from perf status tables + PerforationData & perforationData = *subRegion.getPerforationData(); + string_array const & perfStatusTableName = perforationData.getPerfStatusTableName(); + FunctionManager & functionManager = FunctionManager::getInstance(); + // Get dt for local perforations + for( integer i=0; i( perfStatusTableName[i] ); + setNextDtFromTable( tableFunction, currentTime, nextDt_perf ); + } + nextDt = MpiWrapper::min< real64 >( nextDt_perf ); + // Find min dt including rate and status tables + real64 const nextDt_orig = nextDt; + setNextDtFromTables( currentTime, nextDt ); + //if( m_nonlinearSolverParameters.getLogLevel() > 0 && nextDt < nextDt_orig ) + if( getLogLevel() > 0 && nextDt < nextDt_orig ) + GEOS_LOG_RANK_0( GEOS_FMT( "{}: next time step based on tables coordinates = {}", getName(), nextDt )); + return nextDt; +} bool WellControls::isWellOpen() const { return getWellStatus() == WellControls::Status::OPEN; @@ -488,6 +522,8 @@ void WellControls::implicitStepSetup( real64 const & time_n, ElementRegionManager & elemManager, WellElementSubRegion & subRegion ) { + + GEOS_UNUSED_VAR( elemManager ); // Set perforation status setPerforationStatus( time_n, subRegion ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp index 15ce367023f..eea9f070f60 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp @@ -174,7 +174,16 @@ class WellControls : public dataRepository::Group //public PhysicsSolverBase * @param time_n the current time */ virtual void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) = 0; - + /** + * @brief function to set the next time step size + * @param[in] currentTime the current time + * @param[in] currentDt the current time step size + * @param[in] domain the domain object + * @return the prescribed time step size + */ + real64 setNextDt( real64 const & currentTime, + real64 const & currentDt, + WellElementSubRegion & subRegion ); // Bring the base class implicitStepSetup into scope to avoid hiding the overloaded virtual function diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp index ef2c0f29ff4..8778b7d7ec8 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp @@ -74,6 +74,10 @@ WellManager::WellManager( string const & name, setApplyDefaultValue( 1 ). setDescription( "Flag indicating whether local (cell-wise) chopping of negative compositions is allowed" ); + this->registerWrapper( viewKeyStruct::timeStepFromTablesFlagString(), &m_timeStepFromTables ). + setApplyDefaultValue( 0 ). + setInputFlag( dataRepository::InputFlags::OPTIONAL ). + setDescription ( "Choose time step to honor rates/bhp tables time intervals" ); } Group * WellManager::createChild( string const & childKey, string const & childName ) @@ -112,32 +116,37 @@ void WellManager::expandObjectCatalogs() void WellManager::registerDataOnMesh( Group & meshBodies ) { - if( isCompositional() ) + + //std::string const & flowSolverName = getParent().getName();//getGroup< CompositionalMultiphaseBase >().getName(); + // CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); + + forDiscretizationOnMeshTargets( meshBodies, [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) { - //std::string const & flowSolverName = getParent().getName();//getGroup< CompositionalMultiphaseBase >().getName(); - // CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); - forDiscretizationOnMeshTargets( meshBodies, [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) + ElementRegionManager & elemManager = mesh.getElemManager(); + + elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) { - ElementRegionManager & elemManager = mesh.getElemManager(); + WellControls & well = getWellControls( subRegion ); + //well.setFlowSolverName( flowSolver.getName() ); + well.registerWellDataOnMesh( subRegion ); + well.setThermal( isThermal() ); + m_numFluidPhases = well.numFluidPhases(); + m_numFluidComponents = well.numFluidComponents(); + - elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, - [&]( localIndex const, - WellElementSubRegion & subRegion ) - { - CompositionalMultiphaseWell & well = getCompositionalMultiphaseWell( subRegion ); - //well.setFlowSolverName( flowSolver.getName() ); - well.registerWellDataOnMesh( subRegion ); - well.setThermal( isThermal() ); - m_numFluidPhases = well.numFluidPhases(); - m_numFluidComponents = well.numFluidComponents(); - } ); } ); - // 1. Set key dimensions of the problem - // Empty check needed to avoid errors when running in schema generation mode. + } ); + // 1. Set key dimensions of the problem + // Empty check needed to avoid errors when running in schema generation mode. + if( isCompositional() ) + { + // 1 pressure + NC compositions + 1 connectionRate + temp if thermal m_numDofPerWellElement = isThermal() ? m_numFluidComponents + 3 : m_numFluidComponents + 2; @@ -147,7 +156,10 @@ void WellManager::registerDataOnMesh( Group & meshBodies ) } else { - // Single phase registration can be added here in the future + // 1 pressure + NC compositions + 1 connectionRate + temp if thermal + m_numDofPerWellElement = isThermal() ? 3 : 2; + // 1 pressure + NC compositions + temp if thermal + m_numDofPerResElement = isThermal() ? 2 : 1; } #if 0 DomainPartition const & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); @@ -217,11 +229,11 @@ void WellManager::registerDataOnMesh( Group & meshBodies ) setDimLabels( 1, fluid.phaseNames() ). reference().resizeDimension< 1 >( m_numPhases ); subRegion.registerField< well::dPhaseVolumeFraction >( getName() ). - reference().resizeDimension< 1, 2 >( m_numPhases, m_numComponents + 2 ); // dP, dT, dC + reference().resizeDimension< 1, 2 >( m_numPhases, m_numComponents + 2 ); // dP, dT, dC subRegion.registerField< well::totalMassDensity >( getName() ); subRegion.registerField< well::dTotalMassDensity >( getName() ). - reference().resizeDimension< 1 >( m_numComponents +2 ); // dP, dT, dC + reference().resizeDimension< 1 >( m_numComponents +2 ); // dP, dT, dC subRegion.registerField< well::phaseVolumeFraction_n >( getName() ). reference().resizeDimension< 1 >( m_numPhases ); @@ -330,7 +342,40 @@ void WellManager::implicitStepSetup( real64 const & time_n, ; } ); } +real64 +WellManager::setNextDt( real64 const & currentTime, const real64 & currentDt, geos::DomainPartition & domain ) +{ + real64 nextDt = PhysicsSolverBase::setNextDt( currentTime, currentDt, domain ); + + if( m_timeStepFromTables ) + { + real64 nextDt_orig = nextDt; + real64 nextDtLocal = nextDt; + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + + WellControls & wellControls = getWellControls( subRegion ); + real64 nextDtWell = wellControls.setNextDt( currentTime, nextDt, subRegion ); + if( nextDtWell < nextDtLocal ) + { + nextDtLocal = nextDtWell; + } + } ); + } ); + // get the minimum across all ranks + nextDt = MpiWrapper::min< real64 >( nextDtLocal ); + if( getLogLevel() > 0 && nextDt < nextDt_orig ) + GEOS_LOG_RANK_0( GEOS_FMT( "{}: next time step based on tables coordinates = {}", getName(), nextDt )); + } + + return nextDt; +} localIndex WellManager::numDofPerWellElement() const { return m_numDofPerWellElement; @@ -496,38 +541,6 @@ void WellManager::assembleSystem( real64 const time, } ); } ); - #if 0 - // assemble the accumulation term in the mass balance equations - assembleAccumulationTerms( time, dt, domain, dofManager, localMatrix, localRhs ); - - - - // then assemble the pressure relations between well elements - assemblePressureRelations( time, dt, domain, dofManager, localMatrix, localRhs ); - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - ElementRegionManager & elementRegionManager = mesh.getElemManager(); - elementRegionManager.forElementRegions< WellElementRegion >( regionNames, - [&]( localIndex const, - WellElementRegion & region ) - { - WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) - .getGroup< WellElementSubRegion >( region.getSubRegionName() ); - assembleWellConstraintTerms( time, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); - } ); - } ); - - // then compute the perforation rates (later assembled by the coupled solver) - computePerforationRates( time, dt, domain ); - - // then assemble the flux terms in the mass balance equations - // get a reference to the degree-of-freedom numbers - // then assemble the flux terms in the mass balance equations - assembleFluxTerms( time, dt, domain, dofManager, localMatrix, localRhs ); -#endif } void WellManager::selectWellConstraint( real64 const & time_n, @@ -744,8 +757,6 @@ WellManager::calculateResidualNorm( real64 const & time_n, localResidualNormalizer.resize( numNorm ); - - globalIndex const rankOffset = dofManager.rankOffset(); string const wellDofKey = dofManager.getKey( wellElementDofName() ); forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp index 66fe3b6b8cd..3675c0ff623 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.hpp @@ -51,7 +51,7 @@ class WellManager : public PhysicsSolverBase public: /// String used to form the solverName used to register single-physics solvers in CoupledSolver - static string coupledSolverAttributePrefix() { return "wellManager"; } + static string coupledSolverAttributePrefix() { return "well"; } /** * @brief main constructor for Group Objects @@ -141,7 +141,7 @@ class WellManager : public PhysicsSolverBase static constexpr char const * useMassFlagString() {return "useMass"; } /// @return string for the nextDt targetRegions wrapper static constexpr char const * targetRegionsString() { return "targetRegions"; } - + static constexpr char const * timeStepFromTablesFlagString() { return "timeStepFromTables"; } static constexpr char const * useTotalMassEquationString() { return "useTotalMassEquation"; } static constexpr char const * allowLocalCompDensChoppingString() { return CompositionalMultiphaseBase::viewKeyStruct::allowLocalCompDensChoppingString(); } @@ -233,6 +233,17 @@ class WellManager : public PhysicsSolverBase DomainPartition & domain ); /* PhysicsSolverBase interfaces */ + /** + * @brief function to set the next time step size + * @param[in] currentTime the current time + * @param[in] currentDt the current time step size + * @param[in] domain the domain object + * @return the prescribed time step size + */ + virtual real64 setNextDt( real64 const & currentTime, + real64 const & currentDt, + DomainPartition & domain ) override; + virtual void setupDofs( DomainPartition const & domain, DofManager & dofManager ) const override; @@ -543,6 +554,9 @@ class WellManager : public PhysicsSolverBase /// flag indicating whether local (cell-wise) chopping of negative compositions is allowed integer m_allowCompDensChopping; + + // flag to enable time step selection base on rates/bhp tables coordinates + integer m_timeStepFromTables; }; } diff --git a/src/coreComponents/schema/schema.xsd b/src/coreComponents/schema/schema.xsd index fe3fbf60f6a..df2aa8a3d37 100644 --- a/src/coreComponents/schema/schema.xsd +++ b/src/coreComponents/schema/schema.xsd @@ -351,10 +351,6 @@ - - - - @@ -495,10 +491,6 @@ - - - - @@ -527,6 +519,10 @@ + + + + @@ -2707,12 +2703,6 @@ Information output from lower logLevels is added with the desired log level - - - - - - @@ -2748,12 +2738,6 @@ Information output from lower logLevels is added with the desired log level - - - - - - @@ -2761,6 +2745,16 @@ Information output from lower logLevels is added with the desired log level + + + + + + + + + + @@ -3548,59 +3542,37 @@ When set to `all` output both convergence & iteration information to a csv.--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + - - - - + + - + - - - - - - - - - + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - Convergence information + - Linear solver information + - Output residual norm + - Solution information (scaling, maximum changes, quality check) + - Time step information + - Solver timers information + - DAS type information +2 + - The summary of declared fields and coupling--> @@ -5671,59 +5400,25 @@ When set to `all` output both convergence & iteration information to a csv.--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - The summary of declared fields and coupling + - Output tolerance computed the given fracture element--> @@ -6236,6 +5880,369 @@ When set to `all` output both convergence & iteration information to a csv.--> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/coreComponents/schema/schema.xsd.other b/src/coreComponents/schema/schema.xsd.other index 78f9b27ac1f..58f098fe3b7 100644 --- a/src/coreComponents/schema/schema.xsd.other +++ b/src/coreComponents/schema/schema.xsd.other @@ -522,7 +522,7 @@ A field can represent a physical variable. (pressure, temperature, global compos - + @@ -565,7 +565,6 @@ A field can represent a physical variable. (pressure, temperature, global compos - @@ -601,7 +600,6 @@ A field can represent a physical variable. (pressure, temperature, global compos - @@ -609,6 +607,7 @@ A field can represent a physical variable. (pressure, temperature, global compos + @@ -850,47 +849,6 @@ A field can represent a physical variable. (pressure, temperature, global compos - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1334,18 +1292,6 @@ A field can represent a physical variable. (pressure, temperature, global compos - - - - - - - - - - - - @@ -1489,6 +1435,63 @@ A field can represent a physical variable. (pressure, temperature, global compos + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1578,7 +1581,7 @@ A field can represent a physical variable. (pressure, temperature, global compos - + @@ -3655,7 +3658,7 @@ A field can represent a physical variable. (pressure, temperature, global compos - + From ce04fdea5dcc5f7fa765dfaea786df8f2bab5f92 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:29:23 -0800 Subject: [PATCH 55/71] singlephase well dev --- .../compositionalMultiphaseWell/bos.xml | 6 +- .../thermalCompressibleWell_base.xml | 8 +-- ...eservoirCompositionalMultiphaseMSWells.cpp | 2 +- ...eservoirCompositionalMultiphaseSSWells.cpp | 2 +- ...eservoirCompositionalMultiphaseMSWells.cpp | 2 +- ...eservoirCompositionalMultiphaseMSWells.cpp | 2 +- ...eservoirCompositionalMultiphaseSSWells.cpp | 2 +- .../wells/CompositionalMultiphaseWell.cpp | 34 ++++----- .../CompositionalMultiphaseWellFields.hpp | 14 ---- .../fluidFlow/wells/SinglePhaseWell.cpp | 6 +- .../fluidFlow/wells/SinglePhaseWell.hpp | 4 +- .../fluidFlow/wells/SinglePhaseWellFields.hpp | 15 ---- .../fluidFlow/wells/WellControls.cpp | 2 +- .../fluidFlow/wells/WellFields.hpp | 70 +++++++++++++++++++ .../fluidFlow/wells/WellManager.cpp | 35 ++++------ .../fluidFlow/wells/WellSolverBaseFields.hpp | 60 +--------------- ...itionalMultiphaseWellConstraintKernels.hpp | 8 +-- .../CompositionalMultiphaseWellKernels.hpp | 4 +- .../wells/kernels/SinglePhaseWellKernels.hpp | 1 + .../SinglePhaseReservoirAndWells.cpp | 23 ++++++ 20 files changed, 147 insertions(+), 153 deletions(-) diff --git a/inputFiles/compositionalMultiphaseWell/bos.xml b/inputFiles/compositionalMultiphaseWell/bos.xml index 6a5a33071d9..75b5a9826ad 100644 --- a/inputFiles/compositionalMultiphaseWell/bos.xml +++ b/inputFiles/compositionalMultiphaseWell/bos.xml @@ -4,7 +4,7 @@ + fieldName="wellElementConnectionRate"/> diff --git a/inputFiles/singlePhaseFlow/thermalCompressibleWell_base.xml b/inputFiles/singlePhaseFlow/thermalCompressibleWell_base.xml index c8ceb637afe..82bb8c492f0 100644 --- a/inputFiles/singlePhaseFlow/thermalCompressibleWell_base.xml +++ b/inputFiles/singlePhaseFlow/thermalCompressibleWell_base.xml @@ -32,12 +32,12 @@ isThermal="1" targetRegions="{ region }"/> - - - - + + diff --git a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp index 83cf41e02f6..0de45dc3362 100644 --- a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp @@ -468,7 +468,7 @@ void testNumericalJacobian( CompositionalMultiphaseReservoirAndWells< Compositio wellElemCompDens.move( hostMemorySpace, false ); arrayView1d< real64 > const & connRate = - subRegion.getField< fields::well::mixtureConnectionRate >(); + subRegion.getField< fields::well::connectionRate >(); connRate.move( hostMemorySpace, false ); // a) compute all the derivatives wrt to the pressure in WELL elem iwelem diff --git a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp index bf01638a399..58fe3e50a05 100644 --- a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp @@ -515,7 +515,7 @@ void testNumericalJacobian( CompositionalMultiphaseReservoirAndWells< Compositio wellElemCompDens.move( hostMemorySpace, false ); arrayView1d< real64 > const & connRate = - subRegion.getField< fields::well::mixtureConnectionRate >(); + subRegion.getField< fields::well::connectionRate >(); connRate.move( hostMemorySpace, false ); // a) compute all the derivatives wrt to the pressure in WELL elem iwelem diff --git a/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp index 3ed0c30607e..8f33df720e6 100644 --- a/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp @@ -378,7 +378,7 @@ void testNumericalJacobian( CompositionalMultiphaseReservoirAndWells<> & solver, wellElemCompDens.move( hostMemorySpace, false ); arrayView1d< real64 > const & connRate = - subRegion.getField< fields::well::mixtureConnectionRate >(); + subRegion.getField< fields::well::connectionRate >(); connRate.move( hostMemorySpace, false ); // a) compute all the derivatives wrt to the pressure in WELL elem iwelem diff --git a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp index bd711598535..308e21b106e 100644 --- a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp @@ -542,7 +542,7 @@ void testNumericalJacobian( CompositionalMultiphaseReservoirAndWells< Compositio wellElemCompDens.move( hostMemorySpace, false ); arrayView1d< real64 > const & connRate = - subRegion.getField< fields::well::mixtureConnectionRate >(); + subRegion.getField< fields::well::connectionRate >(); connRate.move( hostMemorySpace, false ); // a) compute all the derivatives wrt to the pressure in WELL elem iwelem diff --git a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp index 055682b1863..2e368bba5c7 100644 --- a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp @@ -544,7 +544,7 @@ void testNumericalJacobian( CompositionalMultiphaseReservoirAndWells< Compositio wellElemCompDens.move( hostMemorySpace, false ); arrayView1d< real64 > const & connRate = - subRegion.getField< fields::well::mixtureConnectionRate >(); + subRegion.getField< fields::well::connectionRate >(); connRate.move( hostMemorySpace, false ); // a) compute all the derivatives wrt to the pressure in WELL elem iwelem diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 40abf3e1c0d..dbd0de55841 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -197,8 +197,8 @@ void CompositionalMultiphaseWell::registerWellDataOnMesh( WellElementSubRegion & subRegion.registerField< well::globalCompDensity_n >( getName() ). reference().resizeDimension< 1 >( m_numComponents ); - subRegion.registerField< well::mixtureConnectionRate >( getName() ); - subRegion.registerField< well::mixtureConnectionRate_n >( getName() ); + subRegion.registerField< well::connectionRate >( getName() ); + subRegion.registerField< well::connectionRate_n >( getName() ); subRegion.registerField< well::globalCompFraction >( getName() ). setDimLabels( 1, fluid.componentNames() ). @@ -516,7 +516,7 @@ void CompositionalMultiphaseWell::updateVolRatesForConstraint( WellElementSubReg // subRegion data - arrayView1d< real64 const > const & connRate = subRegion.getField< well::mixtureConnectionRate >(); + arrayView1d< real64 const > const & connRate = subRegion.getField< well::connectionRate >(); // fluid data constitutive::MultiFluidBase & fluidSeparator = getMultiFluidSeparator(); @@ -603,7 +603,7 @@ void CompositionalMultiphaseWell::calculateReferenceElementRates( WellElementSub // subRegion data - arrayView1d< real64 const > const & connRate = subRegion.getField< fields::well::mixtureConnectionRate >(); + arrayView1d< real64 const > const & connRate = subRegion.getField< fields::well::connectionRate >(); // fluid data constitutive::MultiFluidBase & fluidSeparator = getMultiFluidSeparator(); @@ -1011,7 +1011,7 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh arrayView1d< real64 > const & wellElemPressure = subRegion.getField< well::pressure >(); arrayView1d< real64 > const & wellElemTemp = subRegion.getField< well::temperature >(); arrayView2d< real64, compflow::USD_COMP > const & wellElemCompDens = subRegion.getField< well::globalCompDensity >(); - arrayView1d< real64 > const & connRate = subRegion.getField< well::mixtureConnectionRate >(); + arrayView1d< real64 > const & connRate = subRegion.getField< well::connectionRate >(); // get the info stored on well elements arrayView2d< real64, compflow::USD_COMP > const & wellElemCompFrac = subRegion.getField< well::globalCompFraction >(); @@ -1268,7 +1268,7 @@ void CompositionalMultiphaseWell::assembleWellAccumulationTerms( real64 const & subRegion.getReference< array1d< globalIndex > >( wellDofKey ); arrayView1d< integer const > const wellElemGhostRank = subRegion.ghostRank(); arrayView1d< integer const > const elemStatus = subRegion.getLocalWellElementStatus(); - arrayView1d< real64 > const mixConnRate = subRegion.getField< fields::well::mixtureConnectionRate >(); + arrayView1d< real64 > const mixConnRate = subRegion.getField< fields::well::connectionRate >(); localIndex rank_offset = dofManager.rankOffset(); forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) { @@ -1302,7 +1302,7 @@ void CompositionalMultiphaseWell::assembleWellAccumulationTerms( real64 const & subRegion.getReference< array1d< globalIndex > >( wellDofKey ); arrayView1d< integer const > const wellElemGhostRank = subRegion.ghostRank(); - arrayView1d< real64 > mixConnRate = subRegion.getField< fields::well::mixtureConnectionRate >(); + arrayView1d< real64 > mixConnRate = subRegion.getField< fields::well::connectionRate >(); localIndex rank_offset = dofManager.rankOffset(); forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) { @@ -1878,7 +1878,7 @@ CompositionalMultiphaseWell::applyWellSystemSolution( DofManager const & dofMana dofManager.addVectorToField( localSolution, wellElementDofName(), - fields::well::mixtureConnectionRate::key(), + fields::well::connectionRate::key(), scalingFactor, connRateMask ); @@ -1908,7 +1908,7 @@ CompositionalMultiphaseWell::applyWellSystemSolution( DofManager const & dofMana { fieldsToBeSync.addElementFields( { fields::well::pressure::key(), fields::well::globalCompDensity::key(), - fields::well::mixtureConnectionRate::key(), + fields::well::connectionRate::key(), fields::well::temperature::key() }, getTargetRegionNames() ); } @@ -1916,7 +1916,7 @@ CompositionalMultiphaseWell::applyWellSystemSolution( DofManager const & dofMana { fieldsToBeSync.addElementFields( { fields::well::pressure::key(), fields::well::globalCompDensity::key(), - fields::well::mixtureConnectionRate::key() }, + fields::well::connectionRate::key() }, getTargetRegionNames() ); } CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, @@ -1983,9 +1983,9 @@ void CompositionalMultiphaseWell::resetStateToBeginningOfStep( ElementRegionMana wellElemGlobalCompDensity.setValues< parallelDevicePolicy<> >( wellElemGlobalCompDensity_n ); arrayView1d< real64 > const & connRate = - subRegion.getField< well::mixtureConnectionRate >(); + subRegion.getField< well::connectionRate >(); arrayView1d< real64 const > const & connRate_n = - subRegion.getField< well::mixtureConnectionRate_n >(); + subRegion.getField< well::connectionRate_n >(); connRate.setValues< parallelDevicePolicy<> >( connRate_n ); @@ -2164,9 +2164,9 @@ void CompositionalMultiphaseWell::saveState( WellElementSubRegion & subRegion ) wellElemGlobalCompDensity_n.setValues< parallelDevicePolicy<> >( wellElemGlobalCompDensity ); arrayView1d< real64 const > const & connRate = - subRegion.getField< fields::well::mixtureConnectionRate >(); + subRegion.getField< fields::well::connectionRate >(); arrayView1d< real64 > const & connRate_n = - subRegion.getField< fields::well::mixtureConnectionRate_n >(); + subRegion.getField< fields::well::connectionRate_n >(); connRate_n.setValues< parallelDevicePolicy<> >( connRate ); arrayView2d< real64 const, compflow::USD_PHASE > const wellElemPhaseVolFrac = @@ -2215,9 +2215,9 @@ void CompositionalMultiphaseWell::implicitStepSetup( real64 const & time_n, wellElemGlobalCompDensity_n.setValues< parallelDevicePolicy<> >( wellElemGlobalCompDensity ); arrayView1d< real64 const > const & connRate = - subRegion.getField< fields::well::mixtureConnectionRate >(); + subRegion.getField< fields::well::connectionRate >(); arrayView1d< real64 > const & connRate_n = - subRegion.getField< fields::well::mixtureConnectionRate_n >(); + subRegion.getField< fields::well::connectionRate_n >(); connRate_n.setValues< parallelDevicePolicy<> >( connRate ); arrayView2d< real64 const, compflow::USD_PHASE > const wellElemPhaseVolFrac = @@ -2328,7 +2328,7 @@ void CompositionalMultiphaseWell::printRates( real64 const & time_n, // subRegion data arrayView1d< real64 const > const & connRate = - subRegion.getField< well::mixtureConnectionRate >(); + subRegion.getField< well::connectionRate >(); integer const useSurfaceCond = useSurfaceConditions(); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWellFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWellFields.hpp index 3ca423cd7ac..4abd716ffc4 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWellFields.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWellFields.hpp @@ -58,21 +58,7 @@ DECLARE_FIELD( globalCompDensity_n, WRITE_AND_READ, "Global component density at the previous converged time step" ); -DECLARE_FIELD( mixtureConnectionRate, - "wellElementMixtureConnectionRate", - array1d< real64 >, - 0, - LEVEL_0, - WRITE_AND_READ, - "Mixture connection rate" ); -DECLARE_FIELD( mixtureConnectionRate_n, - "wellElementMixtureConnectionRate_n", - array1d< real64 >, - 0, - NOPLOT, - WRITE_AND_READ, - "Mixture connection rate at the previous converged time step" ); DECLARE_FIELD( globalCompFraction, "globalCompFraction", diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index 4361f20d1b9..b5d47105036 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -92,7 +92,7 @@ void SinglePhaseWell::registerWellDataOnMesh( WellElementSubRegion & subRegion ) subRegion.registerField< well::gravityCoefficient >( getName() ); PerforationData & perforationData = *subRegion.getPerforationData(); perforationData.registerField< well::gravityCoefficient >( getName() ); - + perforationData.registerField< well::perforationRate >( getName() ); perforationData.registerField< well::dPerforationRate >( getName() ). reference().resizeDimension< 1, 2 >( 2, 2 ); @@ -523,9 +523,9 @@ void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh } ); } } - + PresTempInitializationKernel::SinglePhaseFlowAccessors resSinglePhaseFlowAccessors( elemManager, getFlowSolverName()); - PresTempInitializationKernel::SingleFluidAccessors resSingleFluidAccessors( elemManager,getFlowSolverName() ); + PresTempInitializationKernel::SingleFluidAccessors resSingleFluidAccessors( elemManager, getFlowSolverName() ); // 1) Loop over all perforations to compute an average density // 2) Initialize the reference pressure diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp index a6a23e3cada..5f4a95c80a9 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp @@ -224,7 +224,7 @@ class SinglePhaseWell : public WellControls virtual string resElementDofName() const override; - virtual localIndex numFluidComponents() const override { return 1; } + virtual localIndex numFluidComponents() const override { return 0; } virtual localIndex numFluidPhases() const override { return 1; } @@ -283,7 +283,7 @@ class SinglePhaseWell : public WellControls arrayView1d< real64 > const & localRhs ); struct viewKeyStruct : WellControls::viewKeyStruct { - static constexpr char const * dofFieldString() { return "singlePhaseWellVars"; } + static constexpr char const * dofFieldString() { return "wellVars"; } // control data (not registered on the mesh) static constexpr char const * currentBHPString() { return "currentBHP"; } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWellFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWellFields.hpp index 2cd21f32866..9e0d5472826 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWellFields.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWellFields.hpp @@ -33,21 +33,6 @@ namespace fields namespace well { -DECLARE_FIELD( connectionRate, - "connectionRate", - array1d< real64 >, - 0, - LEVEL_0, - WRITE_AND_READ, - "Connection rate" ); - -DECLARE_FIELD( connectionRate_n, - "connectionRate_n", - array1d< real64 >, - 0, - NOPLOT, - WRITE_AND_READ, - "Connection rate at the previous converged time step" ); DECLARE_FIELD( density_n, "density_n", diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index 7099c06bdcc..746b62b5ab4 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -24,7 +24,7 @@ #include "functions/FunctionManager.hpp" #include "mesh/PerforationFields.hpp" #include "fileIO/Outputs/OutputBase.hpp" -#include "physicsSolvers/fluidFlow/wells/WellSolverBaseFields.hpp" +#include "physicsSolvers/fluidFlow/wells/WellFields.hpp" #include "functions/FunctionManager.hpp" namespace geos { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellFields.hpp index 5f77922f4ee..3bb07399534 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellFields.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellFields.hpp @@ -34,6 +34,21 @@ namespace fields namespace well { +DECLARE_FIELD( connectionRate, + "wellElementConnectionRate", + array1d< real64 >, + 0, + LEVEL_0, + WRITE_AND_READ, + "Connection rate" ); + +DECLARE_FIELD( connectionRate_n, + "wellElementConnectionRate_n", + array1d< real64 >, + 0, + NOPLOT, + WRITE_AND_READ, + "Connection rate at the previous converged time step" ); DECLARE_FIELD( energyPerforationFlux, "energyPerforationFlux", array1d< real64 >, @@ -50,6 +65,61 @@ DECLARE_FIELD( dEnergyPerforationFlux, NO_WRITE, "Derivative of energy perforation flux with respect to pressure temperature and global component density (compositional only)" ); +DECLARE_FIELD( pressure, + "pressure", + array1d< real64 >, + 0, + LEVEL_0, + WRITE_AND_READ, + "Pressure" ); + +DECLARE_FIELD( pressure_n, + "pressure_n", + array1d< real64 >, + 0, + NOPLOT, + WRITE_AND_READ, + "Pressure at the previous converged time step" ); + +DECLARE_FIELD( temperature, + "temperature", + array1d< real64 >, + 0, + LEVEL_0, + WRITE_AND_READ, + "Temperature" ); + +DECLARE_FIELD( temperature_n, + "temperature_n", + array1d< real64 >, + 0, + NOPLOT, + WRITE_AND_READ, + "Temperature at the previous converged time step" ); + +DECLARE_FIELD( gravityCoefficient, + "gravityCoefficient", + array1d< real64 >, + 0, + NOPLOT, + WRITE_AND_READ, + "Gravity coefficient (dot product of gravity acceleration by gravity vector)" ); + +DECLARE_FIELD( pressureScalingFactor, + "pressureScalingFactor", + array1d< real64 >, + 1, + NOPLOT, + NO_WRITE, + "Scaling factors for pressure" ); + +DECLARE_FIELD( temperatureScalingFactor, + "temperatureScalingFactor", + array1d< real64 >, + 1, + NOPLOT, + NO_WRITE, + "Scaling factors for temperature" ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp index 8778b7d7ec8..be47333f532 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp @@ -30,7 +30,7 @@ #include "physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp" #include "physicsSolvers/fluidFlow/wells/WellControls.hpp" -#include "physicsSolvers/fluidFlow/wells/WellSolverBaseFields.hpp" +#include "physicsSolvers/fluidFlow/wells/WellFields.hpp" #include "fileIO/Outputs/OutputBase.hpp" #include "functions/FunctionManager.hpp" namespace geos @@ -144,24 +144,12 @@ void WellManager::registerDataOnMesh( Group & meshBodies ) } ); // 1. Set key dimensions of the problem // Empty check needed to avoid errors when running in schema generation mode. - if( isCompositional() ) - { - - // 1 pressure + NC compositions + 1 connectionRate + temp if thermal - m_numDofPerWellElement = isThermal() ? m_numFluidComponents + 3 : m_numFluidComponents + 2; - // 1 pressure + NC compositions + temp if thermal - m_numDofPerResElement = isThermal() ? m_numFluidComponents + 2 : m_numFluidComponents + 1; - - } - else - { - // 1 pressure + NC compositions + 1 connectionRate + temp if thermal - m_numDofPerWellElement = isThermal() ? 3 : 2; - // 1 pressure + NC compositions + temp if thermal - m_numDofPerResElement = isThermal() ? 2 : 1; - } -#if 0 + // 1 pressure + NC compositions + 1 connectionRate + temp if thermal + m_numDofPerWellElement = isThermal() ? m_numFluidComponents + 3 : m_numFluidComponents + 2; + // 1 pressure + NC compositions + temp if thermal + m_numDofPerResElement = isThermal() ? m_numFluidComponents + 2 : m_numFluidComponents + 1; + #if 0 DomainPartition const & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); ConstitutiveManager const & cm = domain.getConstitutiveManager(); @@ -216,8 +204,8 @@ void WellManager::registerDataOnMesh( Group & meshBodies ) subRegion.registerField< well::globalCompDensity_n >( getName() ). reference().resizeDimension< 1 >( m_numComponents ); - subRegion.registerField< well::mixtureConnectionRate >( getName() ); - subRegion.registerField< well::mixtureConnectionRate_n >( getName() ); + subRegion.registerField< well::connectionRate >( getName() ); + subRegion.registerField< well::connectionRate_n >( getName() ); subRegion.registerField< well::globalCompFraction >( getName() ). setDimLabels( 1, fluid.componentNames() ). @@ -974,7 +962,7 @@ WellManager::applySystemSolution( DofManager const & dofManager, dofManager.addVectorToField( localSolution, wellElementDofName(), - well::mixtureConnectionRate::key(), + well::connectionRate::key(), scalingFactor, connRateMask ); if( isCompositional()) @@ -985,6 +973,7 @@ WellManager::applySystemSolution( DofManager const & dofManager, well::globalCompDensity::key(), scalingFactor, componentMask ); + } if( isThermal() ) { @@ -999,7 +988,7 @@ WellManager::applySystemSolution( DofManager const & dofManager, } // if component density chopping is allowed, some component densities may be negative after the update // these negative component densities are set to zero in this function - if( m_allowCompDensChopping ) + if( isCompositional() && m_allowCompDensChopping ) { chopNegativeDensities( domain ); } @@ -1011,7 +1000,7 @@ WellManager::applySystemSolution( DofManager const & dofManager, stdVector< string > propNames; propNames.emplace_back( well::pressure::key() ); - propNames.emplace_back( well::mixtureConnectionRate::key() ); + propNames.emplace_back( well::connectionRate::key() ); if( isCompositional()) { propNames.emplace_back( well::globalCompDensity::key() ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBaseFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBaseFields.hpp index b9dfebc799b..1c4b639f4f7 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBaseFields.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBaseFields.hpp @@ -31,65 +31,7 @@ namespace fields { namespace well -{ - -DECLARE_FIELD( pressure, - "pressure", - array1d< real64 >, - 0, - LEVEL_0, - WRITE_AND_READ, - "Pressure" ); - -DECLARE_FIELD( pressure_n, - "pressure_n", - array1d< real64 >, - 0, - NOPLOT, - WRITE_AND_READ, - "Pressure at the previous converged time step" ); - -DECLARE_FIELD( temperature, - "temperature", - array1d< real64 >, - 0, - LEVEL_0, - WRITE_AND_READ, - "Temperature" ); - -DECLARE_FIELD( temperature_n, - "temperature_n", - array1d< real64 >, - 0, - NOPLOT, - WRITE_AND_READ, - "Temperature at the previous converged time step" ); - -DECLARE_FIELD( gravityCoefficient, - "gravityCoefficient", - array1d< real64 >, - 0, - NOPLOT, - WRITE_AND_READ, - "Gravity coefficient (dot product of gravity acceleration by gravity vector)" ); - -DECLARE_FIELD( pressureScalingFactor, - "pressureScalingFactor", - array1d< real64 >, - 1, - NOPLOT, - NO_WRITE, - "Scaling factors for pressure" ); - -DECLARE_FIELD( temperatureScalingFactor, - "temperatureScalingFactor", - array1d< real64 >, - 1, - NOPLOT, - NO_WRITE, - "Scaling factors for temperature" ); - -} +{} } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellConstraintKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellConstraintKernels.hpp index 485545cd2d9..229813ee52a 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellConstraintKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellConstraintKernels.hpp @@ -131,7 +131,7 @@ struct ConstraintHelper localIndex const iwelemRef = subRegion.getTopWellElementIndex(); arrayView1d< globalIndex const > const & wellElemDofNumber = subRegion.getReference< array1d< globalIndex > >( wellDofKey ); - arrayView1d< real64 const > const & connRate = subRegion.getField< fields::well::mixtureConnectionRate >(); + arrayView1d< real64 const > const & connRate = subRegion.getField< fields::well::connectionRate >(); arrayView2d< real64 const, compflow::USD_COMP > const & compFrac = subRegion.getField< fields::well::globalCompFraction >(); arrayView3d< real64 const, compflow::USD_COMP_DC > const & dCompFrac_dCompDens = subRegion.getField< fields::well::dGlobalCompFraction_dGlobalCompDensity >(); @@ -238,7 +238,7 @@ struct ConstraintHelper localIndex const iwelemRef = subRegion.getTopWellElementIndex(); arrayView1d< globalIndex const > const & wellElemDofNumber = subRegion.getReference< array1d< globalIndex > >( wellDofKey ); - arrayView1d< real64 const > const & connRate = subRegion.getField< fields::well::mixtureConnectionRate >(); + arrayView1d< real64 const > const & connRate = subRegion.getField< fields::well::connectionRate >(); arrayView2d< real64 const, compflow::USD_COMP > const & compFrac = subRegion.getField< fields::well::globalCompFraction >(); arrayView3d< real64 const, compflow::USD_COMP_DC > const & dCompFrac_dCompDens = subRegion.getField< fields::well::dGlobalCompFraction_dGlobalCompDensity >(); @@ -355,7 +355,7 @@ struct ConstraintHelper localIndex const iwelemRef = subRegion.getTopWellElementIndex(); arrayView1d< globalIndex const > const & wellElemDofNumber = subRegion.getReference< array1d< globalIndex > >( wellDofKey ); - arrayView1d< real64 const > const & connRate = subRegion.getField< fields::well::mixtureConnectionRate >(); + arrayView1d< real64 const > const & connRate = subRegion.getField< fields::well::connectionRate >(); arrayView2d< real64 const, compflow::USD_COMP > const & compFrac = subRegion.getField< fields::well::globalCompFraction >(); arrayView3d< real64 const, compflow::USD_COMP_DC > const & dCompFrac_dCompDens = subRegion.getField< fields::well::dGlobalCompFraction_dGlobalCompDensity >(); @@ -455,7 +455,7 @@ struct ConstraintHelper localIndex const iwelemRef = subRegion.getTopWellElementIndex(); arrayView1d< globalIndex const > const & wellElemDofNumber = subRegion.getReference< array1d< globalIndex > >( wellDofKey ); - arrayView1d< real64 const > const & connRate = subRegion.getField< fields::well::mixtureConnectionRate >(); + arrayView1d< real64 const > const & connRate = subRegion.getField< fields::well::connectionRate >(); arrayView2d< real64 const, compflow::USD_COMP > const & compFrac = subRegion.getField< fields::well::globalCompFraction >(); arrayView3d< real64 const, compflow::USD_COMP_DC > const & dCompFrac_dCompDens = subRegion.getField< fields::well::dGlobalCompFraction_dGlobalCompDensity >(); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp index b01d8adf0ab..654b6bfbe1a 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp @@ -39,7 +39,7 @@ #include "physicsSolvers/fluidFlow/kernels/compositional/SolutionCheckKernel.hpp" #include "physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWellFields.hpp" #include "physicsSolvers/fluidFlow/wells/WellControls.hpp" -#include "physicsSolvers/fluidFlow/wells/WellSolverBaseFields.hpp" +#include "physicsSolvers/fluidFlow/wells/WellFields.hpp" #include "physicsSolvers/fluidFlow/wells/WellPhaseVolumeRateConstraint.hpp" namespace geos @@ -1372,7 +1372,7 @@ class FaceBasedAssemblyKernel m_wellElemDofNumber ( subRegion.getReference< array1d< globalIndex > >( wellDofKey ) ), m_nextWellElemIndex ( subRegion.getReference< array1d< localIndex > >( WellElementSubRegion::viewKeyStruct::nextWellElementIndexString()) ), m_elemStatus( subRegion.getLocalWellElementStatus() ), - m_connRate ( subRegion.getField< fields::well::mixtureConnectionRate >() ), + m_connRate ( subRegion.getField< fields::well::connectionRate >() ), m_wellElemCompFrac ( subRegion.getField< fields::well::globalCompFraction >() ), m_dWellElemCompFrac_dCompDens ( subRegion.getField< fields::well::dGlobalCompFraction_dGlobalCompDensity >() ), m_localMatrix( localMatrix ), diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.hpp index dcb8b61f9be..8365d25c946 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.hpp @@ -33,6 +33,7 @@ #include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" #include "physicsSolvers/fluidFlow/StencilAccessors.hpp" #include "physicsSolvers/fluidFlow/wells/WellControls.hpp" +#include "physicsSolvers/fluidFlow/wells/WellFields.hpp" #include "physicsSolvers/fluidFlow/wells/SinglePhaseWellFields.hpp" #include "physicsSolvers/KernelLaunchSelectors.hpp" diff --git a/src/coreComponents/physicsSolvers/multiphysics/SinglePhaseReservoirAndWells.cpp b/src/coreComponents/physicsSolvers/multiphysics/SinglePhaseReservoirAndWells.cpp index 46cf3257088..5b3d2f05188 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/SinglePhaseReservoirAndWells.cpp +++ b/src/coreComponents/physicsSolvers/multiphysics/SinglePhaseReservoirAndWells.cpp @@ -126,6 +126,29 @@ initializePreSubGroups() Base::initializePreSubGroups(); SinglePhaseBase const * const flowSolver = this->flowSolver(); Base::wellSolver()->setFlowSolverName( flowSolver->getName() ); + + bool const isThermalFlow = flowSolver->getReference< integer >( SinglePhaseBase::viewKeyStruct::isThermalString() ); + bool const isThermalWell = Base::wellSolver()->template getReference< integer >( WellManager::viewKeyStruct::isThermalString() ); + GEOS_THROW_IF( isThermalFlow != isThermalWell, + GEOS_FMT( "{}: the input flag {} must be the same in the flow and well solvers, respectively '{}' and '{}'", + this->getDataContext(), SinglePhaseBase::viewKeyStruct::isThermalString(), + Base::reservoirSolver()->getDataContext(), Base::wellSolver()->getDataContext() ), + InputError, this->getDataContext(), Base::reservoirSolver()->getDataContext(), Base::wellSolver()->getDataContext() ); + DomainPartition & domain = this->template getGroupByPath< DomainPartition >( "/Problem/domain" ); + + this->template forDiscretizationOnMeshTargets<>( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + ElementRegionManager & elemManager = mesh.getElemManager(); + elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, + WellElementSubRegion const & subRegion ) + { + WellControls & wellControls = Base::wellSolver()->getWellControls( subRegion ); + wellControls.setFlowSolverName( flowSolver->getName() ); + + } ); + } ); } template< typename RESERVOIR_SOLVER > From 1a407a4922586e41f632347c332d118ecf6bf0e5 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 27 Jan 2026 06:11:38 -0800 Subject: [PATCH 56/71] branch integrated tests matches geos-dev --- .../benchmarks/Egg/deadOilEgg_base_direct.xml | 8 +- .../Egg/deadOilEgg_base_iterative.xml | 8 +- .../black_oil_wells_saturated_3d.xml | 2 +- .../black_oil_wells_saturated_3d_stone2.xml | 2 +- .../black_oil_wells_unsaturated_3d.xml | 2 +- .../black_oil_wells_unsaturated_3d_stone2.xml | 2 +- .../wells/CompositionalMultiphaseWell.cpp | 9 +- .../fluidFlow/wells/SinglePhaseWell.cpp | 120 +++++++++++++----- .../fluidFlow/wells/WellManager.cpp | 28 ++-- 9 files changed, 123 insertions(+), 58 deletions(-) diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml index 93fe91dcc44..40d16d1a47a 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_direct.xml @@ -445,21 +445,21 @@ + fieldName="wellElementConnectionRate"/> + fieldName="wellElementConnectionRate"/> + fieldName="wellElementConnectionRate"/> + fieldName="wellElementConnectionRate"/> diff --git a/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_iterative.xml b/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_iterative.xml index 523fe01d549..3922880cf1a 100644 --- a/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_iterative.xml +++ b/inputFiles/compositionalMultiphaseWell/benchmarks/Egg/deadOilEgg_base_iterative.xml @@ -447,21 +447,21 @@ + fieldName="wellElementConnectionRate"/> + fieldName="wellElementonnectionRate"/> + fieldName="wellElementConnectionRate"/> + fieldName="wellElementConnectionRate"/> diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d.xml index f91593ea12d..dba3b84b0c5 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d.xml @@ -287,7 +287,7 @@ + fieldName="wellElementConnectionRate"/> diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml index 8ae05610077..a285a0d9773 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_saturated_3d_stone2.xml @@ -288,7 +288,7 @@ + fieldName="wellElementConnectionRate"/> diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml index a964a1ccd88..d2b7a5cd375 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d.xml @@ -251,7 +251,7 @@ + fieldName="wellElementConnectionRate"/> diff --git a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml index f8779107119..297511e60ae 100644 --- a/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml +++ b/inputFiles/compositionalMultiphaseWell/black_oil_wells_unsaturated_3d_stone2.xml @@ -253,7 +253,7 @@ + fieldName="wellElementConnectionRate"/> diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index dbd0de55841..ce40e4423cd 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -251,7 +251,7 @@ void CompositionalMultiphaseWell::registerWellDataOnMesh( WellElementSubRegion & registerWrapper< real64 >( viewKeyStruct::massDensityString() ); registerWrapper< real64 >( viewKeyStruct::currentMassRateString() ); - + m_writeCSV=1; // write rates output header // the rank that owns the reference well element is responsible if( m_writeCSV > 0 && subRegion.isLocallyOwned() ) @@ -2241,12 +2241,7 @@ void CompositionalMultiphaseWell::implicitStepComplete( real64 const & time_n, real64 const & dt, WellElementSubRegion const & subRegion ) { - //WellSolverBase::implicitStepComplete( time_n, dt, subRegion ); - - if( getLogLevel() > 0 ) - { - printRates( time_n, dt, subRegion ); - } + printRates( time_n, dt, subRegion ); } void CompositionalMultiphaseWell::printRates( real64 const & time_n, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index b5d47105036..3160d34ed44 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -115,7 +115,7 @@ void SinglePhaseWell::registerWellDataOnMesh( WellElementSubRegion & subRegion ) registerWrapper< array1d< real64 > >( viewKeyStruct::dCurrentVolRateString() ). setSizedFromParent( 0 ). reference().resizeDimension< 0 >( 2 + isThermal() ); // dP, dT, dQ - + m_writeCSV=1; // write rates output header if( m_writeCSV > 0 && subRegion.isLocallyOwned()) { @@ -179,8 +179,6 @@ void SinglePhaseWell::initializeWellPostInitialConditionsPreSubGroups( WellEleme setGravCoef( subRegion, getParent().getParent().getReference< R1Tensor >( PhysicsSolverManager::viewKeyStruct::gravityVectorString() )); // setup fluid model - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - constitutive::SingleFluidBase & fluid = subRegion.getConstitutiveModel< constitutive::SingleFluidBase >( fluidName ); createSeparator( subRegion ); } void SinglePhaseWell::initializePostInitialConditionsPreSubGroups() @@ -890,29 +888,98 @@ void SinglePhaseWell::assembleWellAccumulationTerms( real64 const & time, string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); SingleFluidBase const & fluid = subRegion.getConstitutiveModel< SingleFluidBase >( fluidName ); - - if( isThermal() ) + if( getWellStatus() == WellControls::Status::OPEN && !m_keepVariablesConstantDuringInitStep ) { - thermalSinglePhaseWellKernels:: - ElementBasedAssemblyKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( isProducer(), - dofManager.rankOffset(), - wellElemDofKey, - subRegion, - fluid, - localMatrix, - localRhs ); + if( isThermal() ) + { + thermalSinglePhaseWellKernels:: + ElementBasedAssemblyKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( isProducer(), + dofManager.rankOffset(), + wellElemDofKey, + subRegion, + fluid, + localMatrix, + localRhs ); + } + else + { + singlePhaseWellKernels:: + ElementBasedAssemblyKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( dofManager.rankOffset(), + wellElemDofKey, + subRegion, + fluid, + localMatrix, + localRhs ); + } + // get the degrees of freedom and ghosting info + arrayView1d< globalIndex const > const & wellElemDofNumber = + subRegion.getReference< array1d< globalIndex > >( wellElemDofKey ); + arrayView1d< integer const > const wellElemGhostRank = subRegion.ghostRank(); + arrayView1d< integer const > const elemStatus = subRegion.getLocalWellElementStatus(); + + arrayView1d< real64 > connRate = subRegion.getField< fields::well::connectionRate >(); + localIndex rank_offset = dofManager.rankOffset(); + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + if( wellElemGhostRank[ei] < 0 ) + { + if( elemStatus[ei]==WellElementSubRegion::WellElemStatus::CLOSED ) + { + connRate[ei] = 0.0; + globalIndex const dofIndex = wellElemDofNumber[ei]; + localIndex const localRow = dofIndex - rank_offset; + + real64 const unity = 1.0; + for( integer i=0; i < m_numDofPerWellElement; i++ ) + { + globalIndex const rindex = localRow+i; + globalIndex const cindex =dofIndex + i; + localMatrix.template addToRow< serialAtomic >( rindex, + &cindex, + &unity, + 1 ); + localRhs[rindex] = 0.0; + } + } + } + } ); } else { - singlePhaseWellKernels:: - ElementBasedAssemblyKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( dofManager.rankOffset(), - wellElemDofKey, - subRegion, - fluid, - localMatrix, - localRhs ); + // Zero accumulation contribution + arrayView1d< globalIndex const > const & wellElemDofNumber = + subRegion.getReference< array1d< globalIndex > >( wellElemDofKey ); + arrayView1d< integer const > const wellElemGhostRank = subRegion.ghostRank(); + + arrayView1d< real64 > connRate = subRegion.getField< fields::well::connectionRate >(); + localIndex rank_offset = dofManager.rankOffset(); + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + if( wellElemGhostRank[ei] < 0 ) + { + connRate[ei] = 0.0; + globalIndex const dofIndex = wellElemDofNumber[ei]; + localIndex const localRow = dofIndex - rank_offset; + + real64 const unity = 1.0; + for( integer i=0; i < m_numDofPerWellElement; i++ ) + { + globalIndex const rindex = localRow+i; + globalIndex const cindex =dofIndex + i; + localMatrix.template addToRow< serialAtomic >( rindex, + &cindex, + &unity, + 1 ); + localRhs[rindex] = 0.0; + } + } + } ); + // zero out current state constraint quantities + getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentBHPString() ) = 0.0; + getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentVolRateString() )=0.0; + getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentVolRateString() )=0.0; } } @@ -1313,12 +1380,7 @@ void SinglePhaseWell::implicitStepComplete( real64 const & time_n, real64 const & dt, WellElementSubRegion const & subRegion ) { -// WellSolverBase::implicitStepComplete( time_n, dt, domain ); - - if( getLogLevel() > 0 ) - { - printRates( time_n, dt, subRegion ); - } + printRates( time_n, dt, subRegion ); } void SinglePhaseWell::printRates( real64 const & time_n, @@ -1326,7 +1388,7 @@ void SinglePhaseWell::printRates( real64 const & time_n, WellElementSubRegion const & subRegion ) { - GEOS_UNUSED_VAR( dt );// FIX THIS tjb + GEOS_UNUSED_VAR( dt ); // FIX THIS tjb // the rank that owns the reference well element is responsible for the calculations below. if( !subRegion.isLocallyOwned() ) { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp index be47333f532..0dee0a4436a 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp @@ -517,15 +517,17 @@ void WellManager::assembleSystem( real64 const time, WellControls & wellControls = getWellControls( subRegion ); // assemble the accumulation term in the mass balance equations wellControls.assembleWellAccumulationTerms( time, dt, subRegion, dofManager, localMatrix, localRhs ); - // assemble the pressure relations between well elements - wellControls.assembleWellPressureRelations( time, dt, subRegion, dofManager, localMatrix, localRhs ); - // assemble well constraint terms - wellControls.assembleWellConstraintTerms( time, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); - // compute the perforation rates (later assembled by the coupled solver) - wellControls.computeWellPerforationRates( time, dt, elementRegionManager, subRegion ); - // assemble the flux terms in the mass balance equations - wellControls.assembleWellFluxTerms( time, dt, subRegion, dofManager, localMatrix, localRhs ); - + if( wellControls.isWellOpen() ) + { + // assemble the pressure relations between well elements + wellControls.assembleWellPressureRelations( time, dt, subRegion, dofManager, localMatrix, localRhs ); + // assemble well constraint terms + wellControls.assembleWellConstraintTerms( time, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); + // compute the perforation rates (later assembled by the coupled solver) + wellControls.computeWellPerforationRates( time, dt, elementRegionManager, subRegion ); + // assemble the flux terms in the mass balance equations + wellControls.assembleWellFluxTerms( time, dt, subRegion, dofManager, localMatrix, localRhs ); + } } ); } ); @@ -667,7 +669,8 @@ void WellManager::initializePostInitialConditionsPreSubGroups() mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, [&]( localIndex const, WellElementSubRegion & subRegion ) { - + // reconstruct local connectivity needed for flux calculations + subRegion.reconstructLocalConnectivity(); WellControls & wellControls = getWellControls( subRegion ); wellControls.initializeWellPostInitialConditionsPreSubGroups( subRegion ); @@ -905,6 +908,11 @@ WellManager::scalingForSystemSolution( DomainPartition & domain, } } + else + { + // Single phase well scaling- not implemented yet + scalingFactor=1.0; + } return LvArray::math::max( scalingFactor, m_minScalingFactor ); } From eea7122c26755cfa731dc866b9862879f429cc05 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 27 Jan 2026 06:19:01 -0800 Subject: [PATCH 57/71] fix unit test schema --- .../singlePhasePoromechanics_WellInFault_fim_smoke.xml | 5 +++-- .../singlePhasePoromechanics_WellInFault_seq_smoke.xml | 5 +++-- src/coreComponents/schema/schema.xsd | 2 ++ src/coreComponents/schema/schema.xsd.other | 4 ++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/inputFiles/poromechanicsFractures/singlePhasePoromechanics_WellInFault_fim_smoke.xml b/inputFiles/poromechanicsFractures/singlePhasePoromechanics_WellInFault_fim_smoke.xml index b40822f5011..ae271a7eb30 100644 --- a/inputFiles/poromechanicsFractures/singlePhasePoromechanics_WellInFault_fim_smoke.xml +++ b/inputFiles/poromechanicsFractures/singlePhasePoromechanics_WellInFault_fim_smoke.xml @@ -50,12 +50,12 @@ + targetRegions="{ wellRegion1, wellRegion2 }"> + targetRegions="{ wellRegion1, wellRegion2 }"> + + diff --git a/src/coreComponents/schema/schema.xsd.other b/src/coreComponents/schema/schema.xsd.other index 58f098fe3b7..2c88afdd50d 100644 --- a/src/coreComponents/schema/schema.xsd.other +++ b/src/coreComponents/schema/schema.xsd.other @@ -522,7 +522,7 @@ A field can represent a physical variable. (pressure, temperature, global compos - + @@ -1581,7 +1581,7 @@ A field can represent a physical variable. (pressure, temperature, global compos - + From db3fa32b75cbe9da6fbaed71591bb5542c8ea663 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Mon, 9 Feb 2026 09:46:01 -0800 Subject: [PATCH 58/71] schema update --- src/coreComponents/schema/schema.xsd | 62 ---------------------- src/coreComponents/schema/schema.xsd.other | 26 +-------- 2 files changed, 2 insertions(+), 86 deletions(-) diff --git a/src/coreComponents/schema/schema.xsd b/src/coreComponents/schema/schema.xsd index c513d4ac536..0d3c021b4dc 100644 --- a/src/coreComponents/schema/schema.xsd +++ b/src/coreComponents/schema/schema.xsd @@ -355,10 +355,6 @@ - - - - @@ -2724,12 +2720,6 @@ Information output from lower logLevels is added with the desired log level - - - - - - @@ -3617,58 +3607,6 @@ Local- Add jump stabilization on interior of macro elements--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/coreComponents/schema/schema.xsd.other b/src/coreComponents/schema/schema.xsd.other index 81a35687b78..e6101f33339 100644 --- a/src/coreComponents/schema/schema.xsd.other +++ b/src/coreComponents/schema/schema.xsd.other @@ -522,7 +522,7 @@ A field can represent a physical variable. (pressure, temperature, global compos - + @@ -566,7 +566,6 @@ A field can represent a physical variable. (pressure, temperature, global compos - @@ -863,27 +862,6 @@ A field can represent a physical variable. (pressure, temperature, global compos - - - - - - - - - - - - - - - - - - - - - @@ -1631,7 +1609,7 @@ A field can represent a physical variable. (pressure, temperature, global compos - + From 21f4a3e8222b8b38eb8da25fd721a89144ae87b9 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 10 Feb 2026 09:16:53 -0800 Subject: [PATCH 59/71] pr review changes --- .../physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp | 5 +++++ .../physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp | 2 +- .../physicsSolvers/fluidFlow/wells/WellManager.cpp | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp index cdc89300129..cef4a225789 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp @@ -82,6 +82,11 @@ WellConstraintBase::WellConstraintBase( string const & name, Group * const paren setInputFlag( InputFlags::OPTIONAL ). setDescription( "Name of the well constraint schedule table when the constraint value is a time dependent function. \n" ); + registerWrapper( viewKeyStruct::constraintValueString(), &m_constraintValue ). + setRTTypeName( rtTypes::CustomTypes::groupNameRef ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Constraint value. \n" ); + } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp index 586f61a17d3..780e19cd024 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp @@ -180,7 +180,7 @@ class WellConstraintBase : public dataRepository::Group static constexpr char const * constraintScheduleTableNameString() { return "constraintScheduleTableName"; } /// String key for the well constraint value - static constexpr char const * constraintValueString() { return "constraintValue"; } + static constexpr char const * constraintValueString() { return "value"; } } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp index 0dee0a4436a..ee182b5d096 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellManager.cpp @@ -134,8 +134,8 @@ void WellManager::registerDataOnMesh( Group & meshBodies ) WellControls & well = getWellControls( subRegion ); //well.setFlowSolverName( flowSolver.getName() ); - well.registerWellDataOnMesh( subRegion ); well.setThermal( isThermal() ); + well.registerWellDataOnMesh( subRegion ); m_numFluidPhases = well.numFluidPhases(); m_numFluidComponents = well.numFluidComponents(); From 74c6fba6dfede3ac0542bc1ca61ba3e63a3208dd Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 10 Feb 2026 09:42:00 -0800 Subject: [PATCH 60/71] fix phase naming --- .../soreideWhitson/1D_100cells/1D_benchmark.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml index cc7e0796fa3..adbf453fa25 100644 --- a/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml +++ b/inputFiles/compositionalMultiphaseFlow/soreideWhitson/1D_100cells/1D_benchmark.xml @@ -51,7 +51,7 @@ useMass="0"> + phaseName="water"/> Date: Tue, 10 Feb 2026 12:20:45 -0800 Subject: [PATCH 61/71] update unittest schema/api --- ...eservoirCompositionalMultiphaseMSWells.cpp | 44 +++++++- ...eservoirCompositionalMultiphaseSSWells.cpp | 46 ++++++-- .../wellsTests/testOpenClosePerf.cpp | 94 +++++++++++++--- ...eservoirCompositionalMultiphaseMSWells.cpp | 66 +++++++++-- .../testReservoirSinglePhaseMSWells.cpp | 106 +++++++++++++++--- ...testReservoirThermalSinglePhaseMSWells.cpp | 105 +++++++++++++++-- ...rvoirThermalSinglePhaseMSWells_RateInj.cpp | 101 +++++++++++++++-- ...eservoirCompositionalMultiphaseMSWells.cpp | 65 +++++++++-- ...eservoirCompositionalMultiphaseSSWells.cpp | 64 +++++++++-- 9 files changed, 601 insertions(+), 90 deletions(-) diff --git a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp index 0de45dc3362..d7bf9d12087 100644 --- a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseMSWells.cpp @@ -94,12 +94,12 @@ char const * xmlInput = targetRegions="{ region }"> - - - + @@ -305,7 +305,7 @@ void testNumericalJacobian( CompositionalMultiphaseReservoirAndWells< Compositio real64 const relTol, LAMBDA && assembleFunction ) { - CompositionalMultiphaseWell & wellSolver = *solver.wellSolver(); + WellManager & wellSolver = *solver.wellSolver(); CompositionalMultiphaseFVM & flowSolver = dynamicCast< CompositionalMultiphaseFVM & >( *solver.reservoirSolver() ); localIndex const NC = flowSolver.numFluidComponents(); @@ -585,7 +585,23 @@ class CompositionalMultiphaseReservoirSolverTest : public ::testing::Test solver->getSystemSolution() ); solver->implicitStepSetup( time, dt, domain ); - solver->wellSolver()->initializeWells( domain, time ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.initializeWell( domain, meshLevel, subRegion, time ); + } ); + } ); } static real64 constexpr time = 0.0; @@ -647,7 +663,23 @@ TEST_F( CompositionalMultiphaseReservoirSolverTest, jacobianNumericalCheck_Accum [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assembleAccumulationTerms( time, dt, domain, solver->getDofManager(), localMatrix, localRhs ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellAccumulationTerms( time, dt, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } diff --git a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp index 58fe3e50a05..0023ec39654 100644 --- a/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testIsothermalReservoirCompositionalMultiphaseSSWells.cpp @@ -94,12 +94,12 @@ char const * xmlInput = targetRegions="{ region }"> - - - - + + @@ -306,7 +306,7 @@ void testNumericalJacobian( CompositionalMultiphaseReservoirAndWells< Compositio real64 const relTol, LAMBDA && assembleFunction ) { - CompositionalMultiphaseWell & wellSolver = *solver.wellSolver(); + WellManager & wellSolver = *solver.wellSolver(); CompositionalMultiphaseFVM & flowSolver = dynamicCast< CompositionalMultiphaseFVM & >( *solver.reservoirSolver() ); localIndex const NC = flowSolver.numFluidComponents(); @@ -656,7 +656,23 @@ class CompositionalMultiphaseReservoirSolverTest : public ::testing::Test solver->getSystemSolution() ); solver->implicitStepSetup( time, dt, domain ); - solver->wellSolver()->initializeWells( domain, time ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.initializeWell( domain, meshLevel, subRegion, time ); + } ); + } ); } static real64 constexpr time = 0.0; @@ -704,7 +720,23 @@ TEST_F( CompositionalMultiphaseReservoirSolverTest, jacobianNumericalCheck_Accum [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assembleAccumulationTerms( time, dt, domain, solver->getDofManager(), localMatrix, localRhs ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellAccumulationTerms( time, dt, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } #endif diff --git a/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp b/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp index 5502909a7c5..dcd0e0e5a57 100644 --- a/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp @@ -57,11 +57,11 @@ char const * PreXmlInput = temperature="297.15" useMass="0"> - - @@ -73,8 +73,8 @@ char const * PreXmlInput = name="minbhp" targetBHP="2e6" referenceElevation="1.25"/> - - + + & solv LAMBDA && perfFunction ) { - CompositionalMultiphaseWell & wellSolver = *solver.wellSolver(); + WellManager & wellSolver = *solver.wellSolver(); typedef stdMap< real64, std::vector< int > > map_type; map_type refVal; @@ -223,7 +223,7 @@ void testPlugBottomUpPerfCheck( CompositionalMultiphaseReservoirAndWells<> & sol LAMBDA && perfFunction ) { - CompositionalMultiphaseWell & wellSolver = *solver.wellSolver(); + WellManager & wellSolver = *solver.wellSolver(); typedef stdMap< real64, std::vector< int > > map_type; map_type refVal; @@ -266,7 +266,7 @@ void testOpenTopDownPerfCheck( CompositionalMultiphaseReservoirAndWells<> & solv LAMBDA && perfFunction ) { - CompositionalMultiphaseWell & wellSolver = *solver.wellSolver(); + WellManager & wellSolver = *solver.wellSolver(); typedef stdMap< real64, std::vector< int > > map_type; map_type refPerfTable; @@ -308,7 +308,7 @@ void testOpenBottomUpPerfCheck( CompositionalMultiphaseReservoirAndWells<> & sol LAMBDA && perfFunction ) { - CompositionalMultiphaseWell & wellSolver = *solver.wellSolver(); + WellManager & wellSolver = *solver.wellSolver(); typedef stdMap< real64, std::vector< int > > map_type; map_type refVal; @@ -522,8 +522,23 @@ TEST_F( CompositionalMultiphaseReservoirSolverTest, plugTopDownPerfCheck ) testPlugTopDownPerfCheck( *solver, domain, [&] ( real64 time ) { - WellSolverBase * wellSolverBase = solver->wellSolver(); - wellSolverBase->setPerforationStatus( time, domain ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.setPerforationStatus( time, subRegion ); + } ); + } ); } ); } @@ -536,8 +551,23 @@ TEST_F( CompositionalMultiphaseReservoirSolverTest, plugBottomUpPerfCheck ) testPlugBottomUpPerfCheck( *solver, domain, [&] ( real64 time ) { - WellSolverBase * wellSolverBase = solver->wellSolver(); - wellSolverBase->setPerforationStatus( time, domain ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.setPerforationStatus( time, subRegion ); + } ); + } ); } ); } TEST_F( CompositionalMultiphaseReservoirSolverTest, openTopDownPerfCheck ) @@ -549,8 +579,24 @@ TEST_F( CompositionalMultiphaseReservoirSolverTest, openTopDownPerfCheck ) testOpenTopDownPerfCheck( *solver, domain, [&] ( real64 time ) { - WellSolverBase * wellSolverBase = solver->wellSolver(); - wellSolverBase->setPerforationStatus( time, domain ); + WellManager * wellSolverBase = solver->wellSolver(); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.setPerforationStatus( time, subRegion ); + } ); + } ); } ); } @@ -563,8 +609,24 @@ TEST_F( CompositionalMultiphaseReservoirSolverTest, openBottomUpPerfCheck ) testOpenBottomUpPerfCheck( *solver, domain, [&] ( real64 time ) { - WellSolverBase * wellSolverBase = solver->wellSolver(); - wellSolverBase->setPerforationStatus( time, domain ); + + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.setPerforationStatus( time, subRegion ); + } ); + } ); } ); } diff --git a/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp index 8f33df720e6..3b5639a588c 100644 --- a/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testReservoirCompositionalMultiphaseMSWells.cpp @@ -57,11 +57,11 @@ char const * xmlInput = temperature="297.15" useMass="0"> - - @@ -73,8 +73,8 @@ char const * xmlInput = name="minbhp" targetBHP="2e6" referenceElevation="1.25"/> - - + @@ -87,8 +87,8 @@ char const * xmlInput = volumeRate="1e-5" injectionStream="{ 0.1, 0.1, 0.1, 0.7 }" injectionTemperature="297.15"/> - + & solver, real64 const relTol, LAMBDA && assembleFunction ) { - CompositionalMultiphaseWell & wellSolver = *solver.wellSolver(); + WellManager & wellSolver = *solver.wellSolver(); CompositionalMultiphaseFVM & flowSolver = dynamicCast< CompositionalMultiphaseFVM & >( *solver.reservoirSolver() ); localIndex const NC = flowSolver.numFluidComponents(); @@ -495,7 +495,23 @@ class CompositionalMultiphaseReservoirSolverTest : public ::testing::Test solver->getSystemSolution() ); solver->implicitStepSetup( time, dt, domain ); - solver->wellSolver()->initializeWells( domain, time ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.initializeWell( domain, meshLevel, subRegion, time ); + } ); + } ); } static real64 constexpr time = 0.0; @@ -541,7 +557,23 @@ TEST_F( CompositionalMultiphaseReservoirSolverTest, jacobianNumericalCheck_Flux [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assembleFluxTerms( time, dt, domain, solver->getDofManager(), localMatrix, localRhs ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellFluxTerms( time, dt, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } @@ -558,7 +590,23 @@ TEST_F( CompositionalMultiphaseReservoirSolverTest, jacobianNumericalCheck_Press [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assemblePressureRelations( time, dt, domain, solver->getDofManager(), localMatrix, localRhs ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellPressureRelations( time, dt, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } diff --git a/src/coreComponents/integrationTests/wellsTests/testReservoirSinglePhaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testReservoirSinglePhaseMSWells.cpp index 8fc88fd94ac..5b15ed993e3 100644 --- a/src/coreComponents/integrationTests/wellsTests/testReservoirSinglePhaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testReservoirSinglePhaseMSWells.cpp @@ -58,10 +58,10 @@ char const * PreXmlInput = discretization="singlePhaseTPFA" targetRegions="{Region1}"> - - @@ -72,9 +72,9 @@ char const * PreXmlInput = - + - @@ -85,8 +85,8 @@ char const * PreXmlInput = - - + + & solver, real64 const relTol, LAMBDA && assembleFunction ) { - SinglePhaseWell & wellSolver = *solver.wellSolver(); + WellManager & wellSolver = *solver.wellSolver(); SinglePhaseFVM< SinglePhaseBase > & flowSolver = dynamicCast< SinglePhaseFVM< SinglePhaseBase > & >( *solver.reservoirSolver() ); CRSMatrix< real64, globalIndex > const & jacobian = solver.getLocalMatrix(); @@ -370,8 +370,23 @@ class SinglePhaseReservoirSolverTest : public ::testing::Test solver->getSystemSolution() ); solver->implicitStepSetup( TIME, DT, domain ); - - solver->wellSolver()->initializeWells( domain, TIME ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.initializeWell( domain, meshLevel, subRegion, TIME ); + } ); + } ); } void TestAssembleCouplingTerms() @@ -400,7 +415,23 @@ class SinglePhaseReservoirSolverTest : public ::testing::Test [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assembleFluxTerms( TIME, DT, domain, solver->getDofManager(), localMatrix, localRhs ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellFluxTerms( TIME, DT, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } @@ -415,7 +446,23 @@ class SinglePhaseReservoirSolverTest : public ::testing::Test [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assemblePressureRelations( TIME, DT, domain, solver->getDofManager(), localMatrix, localRhs ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellPressureRelations( TIME, DT, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } @@ -430,7 +477,23 @@ class SinglePhaseReservoirSolverTest : public ::testing::Test [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assembleAccumulationTerms( TIME, DT, domain, solver->getDofManager(), localMatrix, localRhs ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellAccumulationTerms( TIME, DT, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } @@ -512,7 +575,24 @@ TEST_F( SinglePhaseReservoirSolverInternalWellTest, jacobianNumericalCheck_Flux [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assembleFluxTerms( TIME, DT, domain, solver->getDofManager(), localMatrix, localRhs ); + + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellFluxTerms( TIME, DT, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } diff --git a/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells.cpp index 5baf73b0430..4a8c5a28a67 100644 --- a/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells.cpp @@ -60,11 +60,11 @@ char const * PreXmlInput = discretization="singlePhaseTPFA" targetRegions="{Region1}"> - - @@ -75,9 +75,9 @@ char const * PreXmlInput = - + - - - + + & solver, LAMBDA && assembleFunction ) { GEOS_UNUSED_VAR( testName ); - SinglePhaseWell & wellSolver = *solver.wellSolver(); + WellManager & wellSolver = *solver.wellSolver(); SinglePhaseFVM< SinglePhaseBase > & flowSolver = dynamicCast< SinglePhaseFVM< SinglePhaseBase > & >( *solver.reservoirSolver() ); CRSMatrix< real64, globalIndex > const & jacobian = solver.getLocalMatrix(); @@ -528,7 +528,23 @@ class SinglePhaseReservoirSolverTest : public ::testing::Test solver->getSystemSolution() ); solver->implicitStepSetup( TIME, DT, domain ); - solver->wellSolver()->initializeWells( domain, TIME ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.initializeWell( domain, meshLevel, subRegion, TIME ); + } ); + } ); } void TestAssembleCouplingTerms() @@ -557,7 +573,23 @@ class SinglePhaseReservoirSolverTest : public ::testing::Test [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assembleFluxTerms( TIME, DT, domain, solver->getDofManager(), localMatrix, localRhs ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellFluxTerms( TIME, DT, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } @@ -571,7 +603,23 @@ class SinglePhaseReservoirSolverTest : public ::testing::Test [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assemblePressureRelations( TIME, DT, domain, solver->getDofManager(), localMatrix, localRhs ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellPressureRelations( TIME, DT, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } @@ -586,7 +634,23 @@ class SinglePhaseReservoirSolverTest : public ::testing::Test [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assembleAccumulationTerms( TIME, DT, domain, solver->getDofManager(), localMatrix, localRhs ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellAccumulationTerms( TIME, DT, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } @@ -668,7 +732,24 @@ TEST_F( SinglePhaseReservoirSolverInternalWellTest, jacobianNumericalCheck_Flux [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assembleFluxTerms( TIME, DT, domain, solver->getDofManager(), localMatrix, localRhs ); + + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellFluxTerms( TIME, DT, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } diff --git a/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells_RateInj.cpp b/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells_RateInj.cpp index 07ccbe5626a..5f69fb1b97c 100644 --- a/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells_RateInj.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testReservoirThermalSinglePhaseMSWells_RateInj.cpp @@ -73,13 +73,12 @@ char const * XmlInput = targetRegions="{ region }"> - - - + @@ -310,7 +309,7 @@ void testNumericalJacobian( SinglePhaseReservoirAndWells<> & solver, { GEOS_UNUSED_VAR( testName ); - SinglePhaseWell & wellSolver = *solver.wellSolver(); + WellManager & wellSolver = *solver.wellSolver(); SinglePhaseFVM< SinglePhaseBase > & flowSolver = dynamicCast< SinglePhaseFVM< SinglePhaseBase > & >( *solver.reservoirSolver() ); CRSMatrix< real64, globalIndex > const & jacobian = solver.getLocalMatrix(); @@ -602,8 +601,23 @@ class SinglePhaseReservoirSolverTest : public ::testing::Test solver->getSystemSolution() ); solver->implicitStepSetup( TIME, DT, domain ); - - solver->wellSolver()->initializeWells( domain, TIME ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.initializeWell( domain, meshLevel, subRegion, TIME ); + } ); + } ); } void TestAssembleCouplingTerms() @@ -631,7 +645,23 @@ class SinglePhaseReservoirSolverTest : public ::testing::Test [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assembleFluxTerms( TIME, DT, domain, solver->getDofManager(), localMatrix, localRhs ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellFluxTerms( TIME, DT, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } @@ -645,7 +675,23 @@ class SinglePhaseReservoirSolverTest : public ::testing::Test [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assemblePressureRelations( TIME, DT, domain, solver->getDofManager(), localMatrix, localRhs ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellPressureRelations( TIME, DT, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } @@ -660,7 +706,23 @@ class SinglePhaseReservoirSolverTest : public ::testing::Test [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assembleAccumulationTerms( TIME, DT, domain, solver->getDofManager(), localMatrix, localRhs ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellAccumulationTerms( TIME, DT, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } @@ -717,7 +779,24 @@ TEST_F( SinglePhaseReservoirSolverInternalWellTest, jacobianNumericalCheck_Flux [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assembleFluxTerms( TIME, DT, domain, solver->getDofManager(), localMatrix, localRhs ); + + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellFluxTerms( TIME, DT, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } diff --git a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp index 308e21b106e..4ae6c8f47a6 100644 --- a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseMSWells.cpp @@ -96,14 +96,14 @@ char const * xmlInput = targetRegions="{ region }"> - - - - + + @@ -333,7 +333,7 @@ void testNumericalJacobian( CompositionalMultiphaseReservoirAndWells< Compositio real64 const relTol, bool diag_check, LAMBDA && assembleFunction ) { - CompositionalMultiphaseWell & wellSolver = *solver.wellSolver(); + WellManager & wellSolver = *solver.wellSolver(); CompositionalMultiphaseFVM & flowSolver = dynamicCast< CompositionalMultiphaseFVM & >( *solver.reservoirSolver() ); localIndex const NC = flowSolver.numFluidComponents(); @@ -704,7 +704,24 @@ class CompositionalMultiphaseReservoirSolverTest : public ::testing::Test solver->getSystemSolution() ); solver->implicitStepSetup( time, dt, domain ); - solver->wellSolver()->initializeWells( domain, time ); + + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.initializeWell( domain, meshLevel, subRegion, time ); + } ); + } ); } static real64 constexpr time = 0.0; @@ -790,7 +807,23 @@ TEST_F( CompositionalMultiphaseReservoirSolverTest, jacobianNumericalCheck_Accum [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assembleAccumulationTerms( time, dt, domain, solver->getDofManager(), localMatrix, localRhs ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellAccumulationTerms( time, dt, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } TEST_F( CompositionalMultiphaseReservoirSolverTest, jacobianNumericalCheck_PressureRel ) @@ -804,7 +837,23 @@ TEST_F( CompositionalMultiphaseReservoirSolverTest, jacobianNumericalCheck_Press [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assemblePressureRelations( time, dt, domain, solver->getDofManager(), localMatrix, localRhs ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellPressureRelations( time, dt, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } #endif diff --git a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp index 2e368bba5c7..722be4fb77a 100644 --- a/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testThermalReservoirCompositionalMultiphaseSSWells.cpp @@ -97,14 +97,14 @@ char const * xmlInput = targetRegions="{ region }"> - - - - + + @@ -334,7 +334,7 @@ void testNumericalJacobian( CompositionalMultiphaseReservoirAndWells< Compositio real64 const relTol, bool diag_check, LAMBDA && assembleFunction ) { - CompositionalMultiphaseWell & wellSolver = *solver.wellSolver(); + WellManager & wellSolver = *solver.wellSolver(); CompositionalMultiphaseFVM & flowSolver = dynamicCast< CompositionalMultiphaseFVM & >( *solver.reservoirSolver() ); localIndex const NC = flowSolver.numFluidComponents(); @@ -693,7 +693,23 @@ class CompositionalMultiphaseReservoirSolverTest : public ::testing::Test solver->getSystemSolution() ); solver->implicitStepSetup( time, dt, domain ); - solver->wellSolver()->initializeWells( domain, time ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.initializeWell( domain, meshLevel, subRegion, time ); + } ); + } ); } static real64 constexpr time = 0.0; @@ -779,7 +795,23 @@ TEST_F( CompositionalMultiphaseReservoirSolverTest, jacobianNumericalCheck_Accum [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assembleAccumulationTerms( time, dt, domain, solver->getDofManager(), localMatrix, localRhs ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellAccumulationTerms( time, dt, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } TEST_F( CompositionalMultiphaseReservoirSolverTest, jacobianNumericalCheck_PressureRel ) @@ -793,7 +825,23 @@ TEST_F( CompositionalMultiphaseReservoirSolverTest, jacobianNumericalCheck_Press [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - solver->wellSolver()->assemblePressureRelations( time, dt, domain, solver->getDofManager(), localMatrix, localRhs ); + WellManager & wellSolver = *solver->wellSolver(); + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + GEOS_UNUSED_VAR( meshBodyName ); + ElementRegionManager & elementRegionManager = meshLevel.getElemManager(); + elementRegionManager.forElementRegions< WellElementRegion >( regionNames, + [&]( localIndex const, + WellElementRegion & region ) + { + WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) + .getGroup< WellElementSubRegion >( region.getSubRegionName() ); + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.assembleWellPressureRelations( time, dt, subRegion, solver->getDofManager(), localMatrix, localRhs ); + } ); + } ); } ); } #endif From f732adc2efff596ccb8d5142e80ed3f5731b3eca Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:57:35 -0800 Subject: [PATCH 62/71] update --- src/coreComponents/schema/schema.xsd | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/coreComponents/schema/schema.xsd b/src/coreComponents/schema/schema.xsd index 0d3c021b4dc..f9b0aca8a7f 100644 --- a/src/coreComponents/schema/schema.xsd +++ b/src/coreComponents/schema/schema.xsd @@ -6206,6 +6206,9 @@ See note on referenceReservoirRegion for reservoir condition options--> + + @@ -6221,6 +6224,9 @@ See note on referenceReservoirRegion for reservoir condition options--> + + @@ -6232,6 +6238,9 @@ See note on referenceReservoirRegion for reservoir condition options--> + + @@ -6245,6 +6254,9 @@ See note on referenceReservoirRegion for reservoir condition options--> + + @@ -6256,6 +6268,9 @@ See note on referenceReservoirRegion for reservoir condition options--> + + @@ -6267,6 +6282,9 @@ See note on referenceReservoirRegion for reservoir condition options--> + + @@ -6276,6 +6294,9 @@ See note on referenceReservoirRegion for reservoir condition options--> + + @@ -6287,6 +6308,9 @@ See note on referenceReservoirRegion for reservoir condition options--> + + @@ -6294,6 +6318,9 @@ See note on referenceReservoirRegion for reservoir condition options--> + + From 686ac97fea4b2c85e6e293c69490db1017d6e906 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 10 Feb 2026 14:16:08 -0800 Subject: [PATCH 63/71] rel mode fix --- .../integrationTests/wellsTests/testOpenClosePerf.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp b/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp index dcd0e0e5a57..d0826f8b9f4 100644 --- a/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp +++ b/src/coreComponents/integrationTests/wellsTests/testOpenClosePerf.cpp @@ -579,7 +579,6 @@ TEST_F( CompositionalMultiphaseReservoirSolverTest, openTopDownPerfCheck ) testOpenTopDownPerfCheck( *solver, domain, [&] ( real64 time ) { - WellManager * wellSolverBase = solver->wellSolver(); WellManager & wellSolver = *solver->wellSolver(); wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, MeshLevel & meshLevel, From e19eebcd33647da3f7cfaeef91067ee99f00154e Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Wed, 11 Feb 2026 06:28:30 -0800 Subject: [PATCH 64/71] cleanup --- .../wells/CompositionalMultiphaseWell.cpp | 2 +- .../wells/CompositionalMultiphaseWell.hpp | 9 +- .../fluidFlow/wells/SinglePhaseWell.cpp | 114 ------------------ 3 files changed, 5 insertions(+), 120 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index ce40e4423cd..6b489273e05 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -251,7 +251,7 @@ void CompositionalMultiphaseWell::registerWellDataOnMesh( WellElementSubRegion & registerWrapper< real64 >( viewKeyStruct::massDensityString() ); registerWrapper< real64 >( viewKeyStruct::currentMassRateString() ); - m_writeCSV=1; + // write rates output header // the rank that owns the reference well element is responsible if( m_writeCSV > 0 && subRegion.isLocallyOwned() ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp index 495ba0908d5..6ee60202255 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp @@ -145,10 +145,10 @@ class CompositionalMultiphaseWell : public WellControls arrayView1d< real64 > const & localRhs ) override; /**@}*/ /** - * @defgroup Solver Interface Functions + * @defgroup Well Interface Functions - required by WellManager and WellNewtonSolver * * These functions provide the primary interface that is required for derived classes - * The "Well" versions apply to individual well subRegions, whereas the others apply to all wells + * The "Well" versions apply to individual well subRegions */ /**@{*/ @@ -223,6 +223,7 @@ class CompositionalMultiphaseWell : public WellControls implicitStepComplete( real64 const & time, real64 const & dt, WellElementSubRegion const & subRegion ) override; + virtual void initializeWellPostInitialConditionsPreSubGroups( WellElementSubRegion & subRegion )override; virtual void printRates( real64 const & time_n, @@ -307,10 +308,8 @@ class CompositionalMultiphaseWell : public WellControls /** * @brief Sets all the negative component densities (if any) to zero. - * @param domain the physical domain object + * @param subRegion the well subregion containing all the primary and dependent fields */ - void chopNegativeDensities( DomainPartition & domain ); - void chopNegativeDensities( WellElementSubRegion & subRegion ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index 3160d34ed44..dd3c721ed22 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -615,66 +615,6 @@ void SinglePhaseWell::initializeWell( DomainPartition & domain, MeshLevel & mesh } -void SinglePhaseWell::shutDownWell( WellElementSubRegion & subRegion, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) -{ - GEOS_MARK_FUNCTION; - - string const wellDofKey = dofManager.getKey( wellElementDofName() ); - - - - if( isWellOpen( ) ) - { - return; - } - - globalIndex const rankOffset = dofManager.rankOffset(); - - arrayView1d< integer const > const ghostRank = - subRegion.getReference< array1d< integer > >( ObjectManagerBase::viewKeyStruct::ghostRankString() ); - arrayView1d< globalIndex const > const dofNumber = - subRegion.getReference< array1d< globalIndex > >( wellDofKey ); - - arrayView1d< real64 const > const pres = - subRegion.getField< fields::well::pressure >(); - arrayView1d< real64 const > const connRate = - subRegion.getField< fields::well::connectionRate >(); - - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) - { - if( ghostRank[ei] >= 0 ) - { - return; - } - - globalIndex const dofIndex = dofNumber[ei]; - localIndex const localRow = dofIndex - rankOffset; - real64 rhsValue; - - // 4.1. Apply pressure value to the matrix/rhs - FieldSpecificationEqual::SpecifyFieldValue( dofIndex, - rankOffset, - localMatrix, - rhsValue, - pres[ei], // freeze the current pressure value - pres[ei] ); - localRhs[localRow] = rhsValue; - - // 4.2. Apply rate value to the matrix/rhs - FieldSpecificationEqual::SpecifyFieldValue( dofIndex + 1, - rankOffset, - localMatrix, - rhsValue, - connRate[ei], // freeze the current pressure value - connRate[ei] ); - localRhs[localRow + 1] = rhsValue; - - } ); - -} real64 SinglePhaseWell::updateWellState( ElementRegionManager const & elemManager, WellElementSubRegion & subRegion ) { GEOS_MARK_FUNCTION; @@ -682,60 +622,6 @@ real64 SinglePhaseWell::updateWellState( ElementRegionManager const & elemManage updateSubRegionState( elemManager, subRegion ); return 0.0; } -#if 0 -void SinglePhaseWell::assembleSystem( real64 const time, - real64 const dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) -{ - string const wellDofKey = dofManager.getKey( wellElementDofName()); - - - // selects constraints one of 2 ways - // wellEstimator flag set to 0 => orginal logic rates are computed during update state and constraints are selected every newton - // iteration - // wellEstimator flag > 0 => well esitmator solved for each constraint and then selects the constraint - // => estimator solve only performed first "wellEstimator" iterations - NonlinearSolverParameters const & nonlinearParams = getNonlinearSolverParameters(); - selectWellConstraint( time, dt, nonlinearParams.m_numNewtonIterations, domain ); - - - // assemble the accumulation term in the mass balance equations - assembleAccumulationTerms( time, dt, domain, dofManager, localMatrix, localRhs ); - - // then assemble the pressure relations between well elements - //assemblePressureRelations( time, dt, domain, dofManager, localMatrix, localRhs ); - { - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - ElementRegionManager & elementRegionManager = mesh.getElemManager(); - elementRegionManager.forElementRegions< WellElementRegion >( regionNames, - [&]( localIndex const, - WellElementRegion & region ) - { - WellElementSubRegion & subRegion = region.getGroup( ElementRegionBase::viewKeyStruct::elementSubRegions() ) - .getGroup< WellElementSubRegion >( region.getSubRegionName() ); - - assembleWellConstraintTerms( time, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); - } ); - } ); - } - // then compute the perforation rates (later assembled by the coupled solver) - computePerforationRates( time, dt, domain ); - - // then assemble the flux terms in the mass balance equations - // get a reference to the degree-of-freedom numbers - // then assemble the flux terms in the mass balance equations - assembleFluxTerms( time, dt, domain, dofManager, localMatrix, localRhs ); - - // then apply a special treatment to the wells that are shut - shutDownWell( time, domain, dofManager, localMatrix, localRhs ); -} -#endif void SinglePhaseWell::assembleWellFluxTerms( real64 const & time, real64 const & dt, From 5d1dd3604a6b9450224738310ce30e431a1aa077 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Wed, 11 Feb 2026 09:37:09 -0800 Subject: [PATCH 65/71] schema update --- .../tableFunctionsFileTests/testTableFunctionsOutput.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreComponents/integrationTests/tableFunctionsFileTests/testTableFunctionsOutput.cpp b/src/coreComponents/integrationTests/tableFunctionsFileTests/testTableFunctionsOutput.cpp index 4bbe92d81db..ae5394e2d26 100644 --- a/src/coreComponents/integrationTests/tableFunctionsFileTests/testTableFunctionsOutput.cpp +++ b/src/coreComponents/integrationTests/tableFunctionsFileTests/testTableFunctionsOutput.cpp @@ -84,12 +84,12 @@ char const * xmlInput = targetRegions="{ region }"> - - - - + + From 45d80bc2c50b4f1e6da69403fa5038a6a9e1babb Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Thu, 12 Feb 2026 08:41:25 -0800 Subject: [PATCH 66/71] lambda capture error --- .../wells/kernels/CompositionalMultiphaseWellKernels.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp index a0c71194971..b9cca35a88b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp @@ -469,7 +469,7 @@ RateInitializationKernel:: std::vector< WellConstraintBase * > const constraints = wellControls.getProdRateConstraints(); // Use first rate constraint to set initial connection rates real64 const rateVal = constraints[0]->getConstraintValue( time ); - forAll< parallelDevicePolicy<> >( subRegionSize, [&] GEOS_HOST_DEVICE ( localIndex const iwelem ) + forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) { connRate[iwelem] = LvArray::math::max( 0.1 * rateVal * phaseDens[iwelem][0][targetPhaseIndex], -1e3 ); From 680eb36dbed1acfb4aad15b903fc3eac4c3e1963 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Thu, 12 Feb 2026 09:20:13 -0800 Subject: [PATCH 67/71] remove std::cout --- .../fluidFlow/wells/CompositionalMultiphaseWell.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 6b489273e05..f4b89d8191e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -1893,15 +1893,13 @@ CompositionalMultiphaseWell::applyWellSystemSolution( DofManager const & dofMana } -#if 1 // if component density chopping is allowed, some component densities may be negative after the update // these negative component densities are set to zero in this function if( m_allowCompDensChopping ) { chopNegativeDensities( subRegion ); } -#endif - std::cout << getTargetRegionNames()[0] << " Well after applyWellSystemSolution: " << std::endl; + // synchronize FieldIdentifiers fieldsToBeSync; if( isThermal() ) From 7c17469a85d3fc386b823c636e7113aad4db03e4 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Fri, 13 Feb 2026 04:56:29 -0800 Subject: [PATCH 68/71] cleanup --- .../fluidFlow/wells/SinglePhaseWell.cpp | 63 ++++--------------- 1 file changed, 13 insertions(+), 50 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index dd3c721ed22..fff6c307b80 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -73,8 +73,6 @@ void SinglePhaseWell::registerWellDataOnMesh( WellElementSubRegion & subRegion ) setConstitutiveNames ( subRegion ); - //DomainPartition const & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); - //ConstitutiveManager const & cm = domain.getConstitutiveManager(); if( m_referenceFluidModelName.empty() ) { m_referenceFluidModelName = getConstitutiveName< SingleFluidBase >( subRegion ); @@ -104,18 +102,9 @@ void SinglePhaseWell::registerWellDataOnMesh( WellElementSubRegion & subRegion ) perforationData.registerField< well::gravityCoefficient >( getName() ); } - registerWrapper< real64 >( viewKeyStruct::currentBHPString() ); - - registerWrapper< array1d< real64 > >( viewKeyStruct::dCurrentBHPString() ). - setSizedFromParent( 0 ). - reference().resizeDimension< 0 >( 2 + isThermal() ); // dP, dT , dQ - registerWrapper< real64 >( viewKeyStruct::currentVolRateString() ); - registerWrapper< array1d< real64 > >( viewKeyStruct::dCurrentVolRateString() ). - setSizedFromParent( 0 ). - reference().resizeDimension< 0 >( 2 + isThermal() ); // dP, dT, dQ - m_writeCSV=1; + // write rates output header if( m_writeCSV > 0 && subRegion.isLocallyOwned()) { @@ -218,7 +207,6 @@ void SinglePhaseWell::updateBHPForConstraint( WellElementSubRegion & subRegion ) return; } - localIndex const iwelemRef = subRegion.getTopWellElementIndex(); // subRegion data @@ -235,42 +223,25 @@ void SinglePhaseWell::updateBHPForConstraint( WellElementSubRegion & subRegion ) arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > const & dens = fluid.density(); arrayView3d< real64 const, constitutive::singlefluid::USD_FLUID_DER > const & dDens = fluid.dDensity(); - // control data - - string const wellControlsName = getName(); real64 const & refGravCoef = getReferenceGravityCoef(); + real64 & currentBHP = getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentBHPString() ); - real64 & currentBHP = - getReference< real64 >( SinglePhaseWell::viewKeyStruct::currentBHPString() ); - arrayView1d< real64 > const & dCurrentBHP = - getReference< array1d< real64 > >( SinglePhaseWell::viewKeyStruct::dCurrentBHPString() ); - - geos::internal::kernelLaunchSelectorThermalSwitch( isThermal(), [&] ( auto ISTHERMAL ) + // bring everything back to host, capture the scalars by reference + forAll< serialPolicy >( 1, [pres, + dens, + dDens, + wellElemGravCoef, + ¤tBHP, + &iwelemRef, + &refGravCoef] ( localIndex const ) { - integer constexpr IS_THERMAL = ISTHERMAL(); - // bring everything back to host, capture the scalars by reference - forAll< serialPolicy >( 1, [pres, - dens, - dDens, - wellElemGravCoef, - ¤tBHP, - &dCurrentBHP, - &iwelemRef, - &refGravCoef] ( localIndex const ) - { - real64 const diffGravCoef = refGravCoef - wellElemGravCoef[iwelemRef]; - currentBHP = pres[iwelemRef] + dens[iwelemRef][0] * diffGravCoef; - dCurrentBHP[DerivOffset::dP] = 1.0 + dDens[iwelemRef][0][DerivOffset::dP] *diffGravCoef; - if constexpr ( IS_THERMAL ) - { - dCurrentBHP[DerivOffset::dT] = dDens[iwelemRef][0][DerivOffset::dT] * diffGravCoef; - } - } ); + real64 const diffGravCoef = refGravCoef - wellElemGravCoef[iwelemRef]; + currentBHP = pres[iwelemRef] + dens[iwelemRef][0] * diffGravCoef; } ); GEOS_LOG_LEVEL_BY_RANK( logInfo::WellControl, GEOS_FMT( "{}: The BHP (at the specified reference elevation) = {} Pa", - wellControlsName, currentBHP ) ); + getName(), currentBHP ) ); } @@ -291,10 +262,6 @@ void SinglePhaseWell::calculateReferenceElementRates( WellElementSubRegion & sub arrayView1d< real64 const > const & connRate = subRegion.getField< well::connectionRate >(); - - // control data - - // fluid data constitutive::SingleFluidBase & fluidSeparator = getSingleFluidSeparator(); arrayView2d< real64 const, constitutive::singlefluid::USD_FLUID > const & dens = fluidSeparator.density(); @@ -457,7 +424,6 @@ real64 SinglePhaseWell::updateSubRegionState( ElementRegionManager const & elemM // update the current BHP updateBHPForConstraint( subRegion ); - } return 0.0; // change in phasevolume fraction doesnt apply } @@ -684,7 +650,6 @@ void SinglePhaseWell::assembleWellConstraintTerms( real64 const & time_n, return; } { - // tjb wellControls.forSubGroups< BHPConstraint, MassConstraint, VolumeRateConstraint >( [&]( auto & constraint ) forSubGroups< BHPConstraint, InjectionConstraint< VolumeRateConstraint >, ProductionConstraint< VolumeRateConstraint > >( [&]( auto & constraint ) { if( constraint.getName() == getCurrentConstraint()->getName()) @@ -869,8 +834,6 @@ void SinglePhaseWell::assembleWellAccumulationTerms( real64 const & time, } } - - void SinglePhaseWell::computeWellPerforationRates( real64 const & time_n, real64 const & GEOS_UNUSED_PARAM( dt ), ElementRegionManager const & elemManager, From 3c12552255d2135874f1a8b347c05b9c6aa21aca Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Fri, 13 Feb 2026 09:17:33 -0800 Subject: [PATCH 69/71] merge fixes --- .../wells/CompositionalMultiphaseWell.cpp | 58 ++----------------- .../fluidFlow/wells/SinglePhaseWell.cpp | 15 +++-- 2 files changed, 12 insertions(+), 61 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index cacd6428136..b000d57a178 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -352,44 +352,6 @@ void CompositionalMultiphaseWell::validateFluidModel( } } } - -void CompositionalMultiphaseWell::validateInjectionStreams( WellElementSubRegion const & subRegion ) const -{ - WellControls const & wellControls = getWellControls( subRegion ); - - // check well injection stream for injectors - if( wellControls.isInjector()) - { - arrayView1d< real64 const > const & injectionStream = wellControls.getInjectionStream(); - - integer const streamSize = injectionStream.size(); - GEOS_THROW_IF( ( streamSize == 0 ), - "WellControls " << wellControls.getName() << - " : Injection stream not specified for well " << subRegion.getName(), - InputError ); - GEOS_THROW_IF( ( streamSize != m_numComponents ), - "WellControls " << wellControls.getName() << - " : Injection stream for well " << subRegion.getName() << " should have " << - m_numComponents << " components.", - InputError ); - - real64 compFracSum = 0; - for( integer ic = 0; ic < m_numComponents; ++ic ) - { - real64 const compFrac = injectionStream[ic]; - GEOS_THROW_IF( ( compFrac < 0.0 ) || ( compFrac > 1.0 ), - "WellControls " << wellControls.getDataContext() << - ": Invalid injection stream for well " << subRegion.getName(), - InputError, wellControls.getDataContext() ); - compFracSum += compFrac; - } - GEOS_THROW_IF( ( compFracSum < 1.0 - std::numeric_limits< real64 >::epsilon() ) || - ( compFracSum > 1.0 + std::numeric_limits< real64 >::epsilon() ), - "WellControls " << wellControls.getDataContext() << - ": Invalid injection stream for well " << subRegion.getName(), - InputError, wellControls.getDataContext() ); - } -} void CompositionalMultiphaseWell::validateWellConstraints( real64 const & time_n, real64 const & GEOS_UNUSED_PARAM( dt ), @@ -416,9 +378,8 @@ void CompositionalMultiphaseWell::validateWellConstraints( real64 const & time_n string_array const & targetRegionsNames = flowSolver.getTargetRegionNames(); auto const pos = std::find( targetRegionsNames.begin(), targetRegionsNames.end(), regionName ); GEOS_ERROR_IF( pos == targetRegionsNames.end(), - GEOS_FMT( "Region {} is not a target of the reservoir solver and cannot be used for referenceReservoirRegion in WellControl {}.", - regionName, wellControls.getName() ), - getDataContext() ); + GEOS_FMT( "{}: Region {} is not a target of the reservoir solver and cannot be used for referenceReservoirRegion in WellControl {}.", + getDataContext(), regionName, getName() ) ); } @@ -1398,8 +1359,7 @@ CompositionalMultiphaseWell::calculateLocalWellResidualNorm( real64 const & time string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); - WellControls const & wellControls = getWellControls( subRegion ); - + // step 1: compute the norm in the subRegion if( !isWellOpen() ) @@ -1407,7 +1367,7 @@ CompositionalMultiphaseWell::calculateLocalWellResidualNorm( real64 const & time for( integer i = 0; i < numNorm; ++i ) { localResidualNorm[i] = 0.0; - localResidualNormalizer[i] = m_nonlinearSolverParameters.m_minNormalizer; + localResidualNormalizer[i] = nonlinearSolverParameters.m_minNormalizer; } } else if( isThermal() ) @@ -1463,15 +1423,7 @@ CompositionalMultiphaseWell::calculateLocalWellResidualNorm( real64 const & time localResidualNorm[0] = subRegionResidualNorm[0]; } } - } - else - { - for( integer i=0; i( SinglePhaseStatistics::regionStatisticsName() ); - setRegionAveragePressure( stats.averagePressure ); - setRegionAverageTemperature( stats.averageTemperature ); + GEOS_ERROR_IF( stats.averagePressure <= 0.0, GEOS_FMT( "No region average quantities computed. WellControl {} referenceReservoirRegion field requires SinglePhaseStatistics to be configured for region {} ", - wellControls.getName(), wellControls.referenceReservoirRegion() ), + getName(), getReferenceReservoirRegion() ), getDataContext()); - wellControls.setRegionAveragePressure( stats.averagePressure ); - wellControls.setRegionAverageTemperature( stats.averageTemperature ); + setRegionAveragePressure( stats.averagePressure ); + setRegionAverageTemperature( stats.averageTemperature ); } // use region conditions flashPressure = getRegionAveragePressure(); From 5718eb7ae94fd0328563c6f5d41e1c814042f8eb Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Fri, 13 Feb 2026 09:19:20 -0800 Subject: [PATCH 70/71] uncrustify --- .../wells/CompositionalMultiphaseWell.cpp | 108 +++++++++--------- .../fluidFlow/wells/SinglePhaseWell.cpp | 6 +- .../fluidFlow/wells/WellControls.cpp | 3 +- 3 files changed, 58 insertions(+), 59 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index b000d57a178..03b1f9772f1 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -1359,71 +1359,71 @@ CompositionalMultiphaseWell::calculateLocalWellResidualNorm( real64 const & time string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); - - // step 1: compute the norm in the subRegion - if( !isWellOpen() ) - { - for( integer i = 0; i < numNorm; ++i ) - { - localResidualNorm[i] = 0.0; - localResidualNormalizer[i] = nonlinearSolverParameters.m_minNormalizer; - } - } - else if( isThermal() ) - { - real64 subRegionResidualNorm[2]{}; + // step 1: compute the norm in the subRegion - thermalCompositionalMultiphaseWellKernels::ResidualNormKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( m_numComponents, - rankOffset, - wellDofKey, - localRhs, - subRegion, - fluid, - *this, - time_n, - dt, - nonlinearSolverParameters.m_minNormalizer, - subRegionResidualNorm ); - // step 2: reduction across meshBodies/regions/subRegions + if( !isWellOpen() ) + { + for( integer i = 0; i < numNorm; ++i ) + { + localResidualNorm[i] = 0.0; + localResidualNormalizer[i] = nonlinearSolverParameters.m_minNormalizer; + } + } + else if( isThermal() ) + { + real64 subRegionResidualNorm[2]{}; - for( integer i=0; i >( m_numComponents, + rankOffset, + wellDofKey, + localRhs, + subRegion, + fluid, + *this, + time_n, + dt, + nonlinearSolverParameters.m_minNormalizer, + subRegionResidualNorm ); + // step 2: reduction across meshBodies/regions/subRegions + + for( integer i=0; i localResidualNorm[i] ) { - if( subRegionResidualNorm[i] > localResidualNorm[i] ) - { - localResidualNorm[i] = subRegionResidualNorm[i]; - } + localResidualNorm[i] = subRegionResidualNorm[i]; } - } - else - { - real64 subRegionResidualNorm[1]{}; - compositionalMultiphaseWellKernels::ResidualNormKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( m_numComponents, - m_numDofPerWellElement, - rankOffset, - wellDofKey, - localRhs, - subRegion, - fluid, - *this, - time_n, - dt, - nonlinearSolverParameters.m_minNormalizer, - subRegionResidualNorm ); + } + else + { + real64 subRegionResidualNorm[1]{}; + compositionalMultiphaseWellKernels::ResidualNormKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_numComponents, + m_numDofPerWellElement, + rankOffset, + wellDofKey, + localRhs, + subRegion, + fluid, + *this, + time_n, + dt, + nonlinearSolverParameters.m_minNormalizer, + subRegionResidualNorm ); - // step 2: reduction across meshBodies/regions/subRegions - if( subRegionResidualNorm[0] > localResidualNorm[0] ) - { - localResidualNorm[0] = subRegionResidualNorm[0]; - } + // step 2: reduction across meshBodies/regions/subRegions + + if( subRegionResidualNorm[0] > localResidualNorm[0] ) + { + localResidualNorm[0] = subRegionResidualNorm[0]; } - + } + return localResidualNorm; } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index e884a410dbd..939bc4f6c1e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -155,7 +155,7 @@ void SinglePhaseWell::validateWellConstraints( real64 const & time_n, auto const pos = std::find( targetRegionsNames.begin(), targetRegionsNames.end(), regionName ); GEOS_ERROR_IF( pos == targetRegionsNames.end(), GEOS_FMT( "Region {} is not a target of the reservoir solver and cannot be used for referenceReservoirRegion in WellControl {}.", - regionName, getName() ), + regionName, getName() ), getDataContext() ); } @@ -344,11 +344,11 @@ void SinglePhaseWell::updateSeparator( ElementRegionManager const & elemManager, SinglePhaseStatistics::RegionStatistics const & stats = region.getReference< SinglePhaseStatistics::RegionStatistics >( SinglePhaseStatistics::regionStatisticsName() ); - + GEOS_ERROR_IF( stats.averagePressure <= 0.0, GEOS_FMT( "No region average quantities computed. WellControl {} referenceReservoirRegion field requires SinglePhaseStatistics to be configured for region {} ", - getName(), getReferenceReservoirRegion() ), + getName(), getReferenceReservoirRegion() ), getDataContext()); setRegionAveragePressure( stats.averagePressure ); setRegionAverageTemperature( stats.averageTemperature ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index f299787f69c..2f1805a2480 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -271,7 +271,6 @@ void WellControls::postInputInitialization() "The flag to select surface/reservoir conditions must be equal to 0 or 1", InputError, getWrapperDataContext( viewKeyStruct::useSurfaceConditionsString() ) ); - // 6.2) Check incoherent information @@ -295,7 +294,7 @@ void WellControls::postInputInitialization() InputError, getWrapperDataContext( viewKeyStruct::initialPressureCoefficientString() ) ); - + // 12) Create the time-dependent well status table if( m_statusTableName.empty()) { From e33ed8d5f1c0c9f2ba4a62ea8d74b876d2b34049 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Fri, 13 Feb 2026 10:20:47 -0800 Subject: [PATCH 71/71] convert to new schema --- ...oirThermoPoroElastic_Circulation_debug.xml | 71 ++++++++++--------- src/coreComponents/schema/schema.xsd.other | 4 +- 2 files changed, 41 insertions(+), 34 deletions(-) diff --git a/inputFiles/poromechanics/ReservoirThermoPoroElastic_Circulation_debug.xml b/inputFiles/poromechanics/ReservoirThermoPoroElastic_Circulation_debug.xml index b2a0d65d59d..feb3d2e9307 100644 --- a/inputFiles/poromechanics/ReservoirThermoPoroElastic_Circulation_debug.xml +++ b/inputFiles/poromechanics/ReservoirThermoPoroElastic_Circulation_debug.xml @@ -2,12 +2,12 @@ - + - - - - + + + + - - + writeCSV="1"> + + + + + - - + + @@ -162,7 +173,6 @@ - - + targetTime="-1e10"/> - + - - - + poromechanicsSolverName="reservoirPoromechanics"/> - diff --git a/src/coreComponents/schema/schema.xsd.other b/src/coreComponents/schema/schema.xsd.other index 19ef665fd11..d4ab8f870db 100644 --- a/src/coreComponents/schema/schema.xsd.other +++ b/src/coreComponents/schema/schema.xsd.other @@ -522,7 +522,7 @@ A field can represent a physical variable. (pressure, temperature, global compos - + @@ -1609,7 +1609,7 @@ A field can represent a physical variable. (pressure, temperature, global compos - +