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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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 0ba237712bbde83c95025f22e428a64606e0b3cc Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Tue, 14 Oct 2025 15:04:28 -0700 Subject: [PATCH 13/41] well estimator dev --- .../physicsSolvers/PhysicsSolverBase.cpp | 12 +- .../physicsSolvers/PhysicsSolverBase.hpp | 8 +- .../wells/CompositionalMultiphaseWell.cpp | 307 +++++++++-- .../wells/CompositionalMultiphaseWell.hpp | 39 +- .../fluidFlow/wells/SinglePhaseWell.cpp | 13 +- .../fluidFlow/wells/SinglePhaseWell.hpp | 12 +- .../fluidFlow/wells/WellControls.cpp | 5 + .../fluidFlow/wells/WellControls.hpp | 9 +- .../fluidFlow/wells/WellSolverBase.cpp | 467 ++++++++++++++++- .../fluidFlow/wells/WellSolverBase.hpp | 63 ++- .../CoupledReservoirAndWellKernels.hpp | 477 +++++++++++++++++- 11 files changed, 1344 insertions(+), 68 deletions(-) diff --git a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp index 7c3da3cc8cb..1755f500b59 100644 --- a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp @@ -1292,7 +1292,8 @@ void PhysicsSolverBase::debugOutputSystem( real64 const & time, integer const cycleNumber, integer const nonlinearIteration, ParallelMatrix const & matrix, - ParallelVector const & rhs ) const + ParallelVector const & rhs, + string const & tag ) const { // special case when flag value > 2 if( m_writeLinearSystem > 2 && cycleNumber < m_writeLinearSystem ) @@ -1302,7 +1303,7 @@ void PhysicsSolverBase::debugOutputSystem( real64 const & time, time, cycleNumber, nonlinearIteration, - getName() + "_mat", + getName() + "_mat"+tag, "System matrix", m_writeLinearSystem == 1, m_writeLinearSystem >= 2 ); @@ -1311,7 +1312,7 @@ void PhysicsSolverBase::debugOutputSystem( real64 const & time, time, cycleNumber, nonlinearIteration, - getName() + "_rhs", + getName() + "_rhs"+tag, "System right-hand side", m_writeLinearSystem == 1, m_writeLinearSystem >= 2 ); @@ -1320,7 +1321,8 @@ void PhysicsSolverBase::debugOutputSystem( real64 const & time, void PhysicsSolverBase::debugOutputSolution( real64 const & time, integer const cycleNumber, integer const nonlinearIteration, - ParallelVector const & solution ) const + ParallelVector const & solution, + string const & tag ) const { // special case when flag value > 2 if( m_writeLinearSystem > 2 && cycleNumber < m_writeLinearSystem ) @@ -1330,7 +1332,7 @@ void PhysicsSolverBase::debugOutputSolution( real64 const & time, time, cycleNumber, nonlinearIteration, - getName() + "_sol", + getName() + "_sol"+tag, "System solution", m_writeLinearSystem == 1, m_writeLinearSystem >= 2 ); diff --git a/src/coreComponents/physicsSolvers/PhysicsSolverBase.hpp b/src/coreComponents/physicsSolvers/PhysicsSolverBase.hpp index 0ee65309d95..42b39f66d20 100644 --- a/src/coreComponents/physicsSolvers/PhysicsSolverBase.hpp +++ b/src/coreComponents/physicsSolvers/PhysicsSolverBase.hpp @@ -463,13 +463,15 @@ class PhysicsSolverBase : public ExecutableGroup * @param nonlinearIteration current nonlinear iteration number * @param matrix system matrix * @param rhs system right-hand side vector + * @param tag option to tag the output */ void debugOutputSystem( real64 const & time, integer const cycleNumber, integer const nonlinearIteration, ParallelMatrix const & matrix, - ParallelVector const & rhs ) const; + ParallelVector const & rhs, + string const & tag="" ) const; /** * @brief Output the linear system solution for debug purposes. @@ -482,7 +484,9 @@ class PhysicsSolverBase : public ExecutableGroup debugOutputSolution( real64 const & time, integer const cycleNumber, integer const nonlinearIteration, - ParallelVector const & solution ) const; + ParallelVector const & solution, + string const & tag ="" ) const; + /** * @brief Update the convergence information and write then into a CSV file diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index defb9f36a3d..fde973cfb61 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -58,7 +58,8 @@ #include "physicsSolvers/fluidFlow/wells/WellLiquidRateConstraint.hpp" #include "physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellConstraintKernels.hpp" - +// tjb wrong place +#include "physicsSolvers/multiphysics/CoupledReservoirAndWellKernels.hpp" #if defined( __INTEL_COMPILER ) #pragma GCC optimize "O0" @@ -1481,6 +1482,93 @@ void CompositionalMultiphaseWell::assembleWellAccumulationTerms( real64 const & } +void +CompositionalMultiphaseWell::applyWellBoundaryConditions( real64 const time_n, + real64 const dt, + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion, + DofManager const & dofManager, + arrayView1d< real64 > const & localRhs, + CRSMatrixView< real64, globalIndex const > const & localMatrix ) +{ + GEOS_UNUSED_VAR( elemManager ); + GEOS_UNUSED_VAR( time_n ); + + using namespace compositionalMultiphaseUtilities; + + BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags; + if( useTotalMassEquation() ) + kernelFlags.set( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ); + + integer const numComps = numFluidComponents(); + + globalIndex const rankOffset = dofManager.rankOffset(); + + + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); + + // if the well is shut, we neglect reservoir-well flow that may occur despite the zero rate + // therefore, we do not want to compute perforation rates and we simply assume they are zero + WellControls const & wellControls = getWellControls( subRegion ); + //bool const detectCrossflow = + // ( wellControls.isInjector() ) && wellControls.isCrossflowEnabled() && + // getLogLevel() >= 1; // since detect crossflow requires communication, we detect it only if the logLevel is sufficiently high + + if( !wellControls.isWellOpen( ) ) + { + return; + } + + PerforationData const * const perforationData = subRegion.getPerforationData(); + + // get the degrees of freedom + string const wellDofKey = dofManager.getKey( wellElementDofName() ); +#if 1 + if( isThermal ( ) ) + { + coupledReservoirAndWellKernels:: + ThermalCompositionalMultiPhaseWellFluxKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( numComps, + wellControls.isProducer(), + dt, + rankOffset, + wellDofKey, + subRegion, + perforationData, + fluid, + kernelFlags, + localRhs, + localMatrix ); + + } + else + { + coupledReservoirAndWellKernels:: + IsothermalCompositionalMultiPhaseWellFluxKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( numComps, + dt, + rankOffset, + wellDofKey, + subRegion, + perforationData, + fluid, + localRhs, + localMatrix, + kernelFlags ); + } +#endif + +} + +void +CompositionalMultiphaseWell::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 ) ) +{} real64 CompositionalMultiphaseWell::calculateWellResidualNorm( real64 const & time_n, @@ -2929,66 +3017,203 @@ void CompositionalMultiphaseWell::printRates( real64 const & time_n, bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, - WellElementSubRegion & subRegion ) + real64 const & dt, + integer const cycleNumber, + integer const coupledIterationNumber, + DomainPartition & domain, + MeshLevel & mesh, + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion, + DofManager const & dofManager ) { WellControls & wellControls = getWellControls( subRegion ); - // create list of all constraints to process - std::vector< WellConstraintBase * > constraintList; - if( wellControls.isProducer() ) + bool useEstimator = coupledIterationNumber < wellControls.estimateSolution(); + + if( useEstimator ) { - constraintList = wellControls.getProdRateConstraints(); - // Solve minimum bhp constraint first - constraintList.insert( constraintList.begin(), wellControls.getMinBHPConstraint() ); + // create list of all constraints to solve + std::vector< WellConstraintBase * > constraintList; + 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 ); + 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 { - constraintList = wellControls.getInjRateConstraints(); - // Solve maximum bhp constraint first; - constraintList.insert( constraintList.begin(), wellControls.getMaxBHPConstraint() ); + // 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 >( 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 ); + 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()); + } - // Get current constraint - WellConstraintBase * limitingConstraint = nullptr; - for( auto & constraint : constraintList ) + return true; +} +void CompositionalMultiphaseWell::solveConstraint( 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( 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() ) { - limitingConstraint = constraint; - // tjb. this is likely not needed. set in update state + 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() )); - 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 ) ) + if( getLogLevel() > 4 ) { - 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_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()); - 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 6a8998fca4f..02d15468503 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp @@ -304,13 +304,21 @@ class CompositionalMultiphaseWell : public WellSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) override; + virtual void applyWellBoundaryConditions( real64 const time_n, + real64 const dt, + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion, + DofManager const & dofManager, + arrayView1d< real64 > const & localRhs, + CRSMatrixView< real64, globalIndex const > const & localMatrix ) 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; - 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 @@ -321,6 +329,13 @@ class CompositionalMultiphaseWell : public WellSolverBase * @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 ) override; + virtual void assemblePressureRelations( real64 const & time_n, real64 const & dt, DomainPartition const & domain, @@ -328,6 +343,7 @@ class CompositionalMultiphaseWell : public WellSolverBase 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 @@ -441,7 +457,14 @@ class CompositionalMultiphaseWell : public WellSolverBase DomainPartition & domain ) override; virtual bool evaluateConstraints( real64 const & time_n, - WellElementSubRegion & subRegion ) override; + real64 const & stepDt, + integer const cycleNumber, + integer const coupledIterationNumber, + DomainPartition & domain, + MeshLevel & mesh, + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion, + DofManager const & dofManager ) override; private: @@ -458,7 +481,7 @@ class CompositionalMultiphaseWell : public WellSolverBase template< typename ... GROUPTYPES > void selectLimitingConstraint( real64 const & time_n, integer const coupledIterationNumber, WellElementSubRegion & subRegion ); - void solveConstraint( std::shared_ptr< WellConstraintBase > constraint, + void solveConstraint( WellConstraintBase * constraint, real64 const & time_n, real64 const & dt, integer const cycleNumber, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index 839fc616411..b7f0b1f7d1a 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, @@ -1767,8 +1767,15 @@ void SinglePhaseWell::printRates( real64 const & time_n, } ); } -bool SinglePhaseWell::evaluateConstraints( real64 const & time_n, - WellElementSubRegion & subRegion ) +bool SinglePhaseWell::evaluateConstraints(real64 const & 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 & subRegion , + DofManager const & GEOS_UNUSED_PARAM( dofManager ) ) { WellControls & wellControls = getWellControls( subRegion ); // create list of all constraints to process diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp index b9294056d26..a0e2164fd6d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp @@ -376,8 +376,16 @@ class SinglePhaseWell : public WellSolverBase WellElementSubRegion const & subRegion, ElementRegionManager const & elemManager ) override; - virtual bool evaluateConstraints( real64 const & time_n, - WellElementSubRegion & subRegion ) override; + virtual bool evaluateConstraints( real64 const & 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 & subRegion , + DofManager const & GEOS_UNUSED_PARAM( dofManager ) ) override; + /** * @brief Create well separator diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index 6477de44973..97b660dc407 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -41,6 +41,7 @@ WellControls::WellControls( string const & name, Group * const parent ) m_rateSign( -1.0 ), m_statusTable( nullptr ), m_wellOpen( false ), + m_estimateSolution( false ), m_constraintSwitch( true ), m_currentConstraint( nullptr ), m_wellStatus( WellControls::Status::OPEN ), @@ -98,6 +99,10 @@ 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 ) " ); +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 >(); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp index 17dd29aeea1..b3b232a0276 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp @@ -267,6 +267,12 @@ class WellControls : public dataRepository::Group */ void setControl( Control const & newControl ) { m_currentControl = newControl; } + /** + * @brief getter for esitmator switch + * @return True if estimate well solution + */ + integer estimateSolution() const { return m_estimateSolution; } + /** * @brief Getter for the reference gravity coefficient * @return the reference gravity coefficient @@ -578,7 +584,8 @@ class WellControls : public dataRepository::Group bool m_wellOpen; - + /// flag to use the estimator + integer m_estimateSolution; /// List of constraints //constraint_array m_ConstraintList; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp index 35f7ecb1993..f5ecf916397 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp @@ -18,7 +18,7 @@ */ #include "WellSolverBase.hpp" - +#include "physicsSolvers/LogLevelsInfo.hpp" #include "mesh/DomainPartition.hpp" #include "mesh/PerforationFields.hpp" #include "mesh/WellElementRegion.hpp" @@ -307,6 +307,45 @@ 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, @@ -317,6 +356,8 @@ void WellSolverBase::selectWellConstraint( real64 const & time_n, GEOS_UNUSED_VAR( dt ); GEOS_UNUSED_VAR( coupledIterationNumber ); + setupWellDofs( domain ); + integer cycleNumber=0; forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, MeshLevel & meshLevel, string_array const & regionNames ) @@ -347,10 +388,40 @@ 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 ); evaluateConstraints( time_n, - subRegion ); + dt, + cycleNumber, + coupledIterationNumber, + domain, + meshLevel, + elementRegionManager, + subRegion, + dofManager ); // 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 @@ -370,6 +441,31 @@ void WellSolverBase::selectWellConstraint( real64 const & time_n, } +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; @@ -384,6 +480,35 @@ 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 ); + my_ctime=my_ctime+1; + /* + if ( !m_useNewCode ) + { + auto iterInfo = currentIter( time_n, dt ); + outputWellDebug( time_n, dt, std::get< 0 >( iterInfo ), std::get< 1 >( iterInfo ), std::get< 2 >( iterInfo ), + domain, dofManager, localMatrix, localRhs ); + } + */ +} + void WellSolverBase::assembleSystem( real64 const time, real64 const dt, DomainPartition & domain, @@ -517,6 +642,11 @@ real64 WellSolverBase::setNextDt( real64 const & currentTime, const real64 & cur FunctionManager & functionManager = FunctionManager::getInstance(); real64 nextDt = PhysicsSolverBase::setNextDt( currentTime, currentDt, domain ); + if( m_nextDt > 0 ) + { + nextDt = m_nextDt; + m_nextDt=-1; + } if( m_timeStepFromTables ) { forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, @@ -551,4 +681,337 @@ real64 WellSolverBase::setNextDt( real64 const & currentTime, const real64 & cur return nextDt; } + +bool WellSolverBase::solveNonlinearSystem( real64 const & time_n, + real64 const & stepDt, + integer const cycleNumber, + DomainPartition & domain, + MeshLevel & mesh, + ElementRegionManager & elemManager, + WellElementSubRegion & subRegion, + DofManager const & dofManager ) +{ + integer const maxNewtonIter = m_nonlinearSolverParameters.m_maxIterNewton; + integer dtAttempt = m_nonlinearSolverParameters.m_numTimeStepAttempts; + integer configurationLoopIter = m_nonlinearSolverParameters.m_numConfigurationAttempts; + integer const minNewtonIter = m_nonlinearSolverParameters.m_minIterNewton; + real64 const newtonTol = m_nonlinearSolverParameters.m_newtonTol; + +// keep residual from previous iteration in case we need to do a line search + real64 lastResidual = 1e99; + integer newtonIter = 0; + real64 scaleFactor = 1.0; + + bool isNewtonConverged = false; + + for( newtonIter = 0; newtonIter < maxNewtonIter; ++newtonIter ) + { + + GEOS_LOG_LEVEL_RANK_0( logInfo::NonlinearSolver, + GEOS_FMT( " Well: {} Est Attempt: {:2}, ConfigurationIter: {:2}, NewtonIter: {:2}", subRegion.getName(), dtAttempt, configurationLoopIter, newtonIter )); + + { + Timer timer( m_timers["assemble"] ); + +// We sync the nonlinear convergence history. The coupled solver parameters are the one being +// used. We want to propagate the info to subsolvers. It can be important for solvers that +// have special treatment for specific iterations. + synchronizeNonlinearSolverParameters(); + +// zero out matrix/rhs before assembly + m_localMatrix.zero(); + m_rhs.zero(); + + arrayView1d< real64 > const localRhs = m_rhs.open(); + +// call assemble to fill the matrix and the rhs + assembleWellSystem( time_n, + stepDt, + elemManager, + subRegion, + dofManager, + m_localMatrix.toViewConstSizes(), + localRhs ); + +// apply boundary conditions to system + applyWellBoundaryConditions( time_n, + stepDt, + elemManager, + subRegion, + dofManager, + localRhs, + m_localMatrix.toViewConstSizes() ); + + m_rhs.close(); + + if( m_assemblyCallback ) + { +// Make a copy of LA objects and ship off to the callback + array1d< real64 > localRhsCopy( m_rhs.localSize() ); + localRhsCopy.setValues< parallelDevicePolicy<> >( m_rhs.values() ); + m_assemblyCallback( m_localMatrix, std::move( localRhsCopy ) ); + } + } + // outputSingleWellDebug( time_n, stepDt, 0, newtonIter, 0, + // mesh, subRegion, dofManager, m_localMatrix.toViewConstSizes(), m_rhs.values() ); + real64 residualNorm = 0; + { + Timer timer( m_timers["convergence check"] ); + +// get residual norm + residualNorm = calculateWellResidualNorm( time_n, stepDt, subRegion, dofManager, m_rhs.values() ); + GEOS_LOG_LEVEL_RANK_0( logInfo::Convergence, + GEOS_FMT( " ( R ) = ( {:4.2e} )", residualNorm ) ); + } + //auto iterInfo = currentIter( time_n, dt ); + //outputSingleWellDebug( time_n, stepDt, 0, newtonIter, 0, + // mesh, subRegion, dofManager, m_localMatrix.toViewConstSizes(), m_rhs.values() ); +// if the residual norm is less than the Newton tolerance we denote that we have +// converged and break from the Newton loop immediately. + if( residualNorm < newtonTol && newtonIter >= minNewtonIter ) + { + isNewtonConverged = true; + break; + } + +// if the residual norm is above the max allowed residual norm, we break from +// the Newton loop to avoid crashes due to Newton divergence + if( residualNorm > m_nonlinearSolverParameters.m_maxAllowedResidualNorm ) + { + string const maxAllowedResidualNormString = NonlinearSolverParameters::viewKeysStruct::maxAllowedResidualNormString(); + GEOS_LOG_LEVEL_RANK_0( logInfo::Convergence, + GEOS_FMT( " The residual norm is above the {} of {}. Newton loop terminated.", + maxAllowedResidualNormString, + m_nonlinearSolverParameters.m_maxAllowedResidualNorm ) ); + isNewtonConverged = false; + break; + } + + + // do line search in case residual has increased + + if( false && m_nonlinearSolverParameters.m_lineSearchAction != NonlinearSolverParameters::LineSearchAction::None + && residualNorm > lastResidual * m_nonlinearSolverParameters.m_lineSearchResidualFactor + && newtonIter >= m_nonlinearSolverParameters.m_lineSearchStartingIteration ) + { + bool lineSearchSuccess = false; + if( m_nonlinearSolverParameters.m_lineSearchInterpType == NonlinearSolverParameters::LineSearchInterpolationType::Linear ) + { + residualNorm = lastResidual; + lineSearchSuccess = lineSearch1( time_n, + stepDt, + cycleNumber, + domain, + elemManager, + subRegion, + mesh, + dofManager, + m_localMatrix.toViewConstSizes(), + m_rhs, + m_solution, + scaleFactor, + residualNorm ); + } + else + { + lineSearchSuccess = lineSearchWithParabolicInterpolation( time_n, + stepDt, + cycleNumber, + newtonIter, + domain, + dofManager, + m_localMatrix.toViewConstSizes(), + m_rhs, + m_solution, + scaleFactor, + lastResidual, + residualNorm ); + } + + if( !lineSearchSuccess ) + { + if( m_nonlinearSolverParameters.m_lineSearchAction == NonlinearSolverParameters::LineSearchAction::Attempt ) + { + GEOS_LOG_LEVEL_RANK_0( logInfo::LineSearch, + " Line search failed to produce reduced residual. Accepting iteration." ); + } + else if( m_nonlinearSolverParameters.m_lineSearchAction == NonlinearSolverParameters::LineSearchAction::Require ) + { +// if line search failed, then break out of the main Newton loop. Timestep will be cut. + GEOS_LOG_LEVEL_RANK_0( logInfo::LineSearch, + " Line search failed to produce reduced residual. Exiting Newton Loop." ); + break; + } + } + } + + { + Timer timer( m_timers["linear solver total"] ); + +// if using adaptive Krylov tolerance scheme, update tolerance. + LinearSolverParameters::Krylov & krylovParams = m_linearSolverParameters.get().krylov; + if( krylovParams.useAdaptiveTol ) + { + krylovParams.relTolerance = newtonIter > 0 ? eisenstatWalker( residualNorm, lastResidual, krylovParams ) : krylovParams.weakestTol; + } + +// TODO: Trilinos currently requires this, re-evaluate after moving to Tpetra-based solvers + if( m_precond ) + { + m_precond->clear(); + } + + { + Timer timer_setup( m_timers["linear solver create"] ); + +// Compose parallel LA matrix/rhs out of local LA matrix/rhs +// + m_matrix.create( m_localMatrix.toViewConst(), dofManager.numLocalDofs(), MPI_COMM_GEOS ); + } + +// Output the linear system matrix/rhs for debugging purposes + string tag = "_"+std::to_string( my_ctime ); + debugOutputSystem( time_n, cycleNumber, newtonIter, m_matrix, m_rhs, tag ); + +// Solve the linear system + solveLinearSystem( dofManager, m_matrix, m_rhs, m_solution ); + +// Increment the solver statistics for reporting purposes + getIterationStats().updateNonlinearIteration( m_linearSolverResult.numIterations ); + +// Output the linear system solution for debugging purposes + debugOutputSolution( time_n, cycleNumber, newtonIter, m_solution, tag ); + } + + { + Timer timer( m_timers["apply solution"] ); + +// Compute the scaling factor for the Newton update + scaleFactor = scalingForWellSystemSolution( subRegion, dofManager, m_solution.values() ); + + GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, + GEOS_FMT( " {}: Global solution scaling factor = {}", getName(), scaleFactor ) ); + + if( !checkWellSystemSolution( subRegion, dofManager, m_solution.values(), scaleFactor ) ) + { +// TODO try chopping (similar to line search) + GEOS_LOG_RANK_0( GEOS_FMT( " {}: Solution check failed. Newton loop terminated.", getName()) ); + break; + } + +// apply the system solution to the fields/variables + applyWellSystemSolution( dofManager, m_solution.values(), scaleFactor, stepDt, domain, mesh, subRegion ); + } + + { + Timer timer( m_timers["update state"] ); + +// update non-primary variables (constitutive models) + + updateWellState( subRegion ); + } + + lastResidual = residualNorm; + } + + return isNewtonConverged; +} + +bool WellSolverBase::lineSearch1( real64 const & time_n, + real64 const & dt, + integer const GEOS_UNUSED_PARAM( 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 ) +{ + Timer timer( m_timers["line search"] ); + + integer const maxNumberLineSearchCuts = m_nonlinearSolverParameters.m_lineSearchMaxCuts; + real64 const lineSearchCutFactor = m_nonlinearSolverParameters.m_lineSearchCutFactor; + + // flag to determine if we should solve the system and apply the solution. If the line + // search fails we just bail. + bool lineSearchSuccess = false; + + real64 residualNorm = lastResidual; + + // scale factor is value applied to the previous solution. In this case we want to + // subtract a portion of the previous solution. + real64 localScaleFactor = -scaleFactor; + real64 cumulativeScale = scaleFactor; + + // main loop for the line search. + for( integer lineSearchIteration = 0; lineSearchIteration < maxNumberLineSearchCuts; ++lineSearchIteration ) + { + // cut the scale factor by half. This means that the scale factors will + // have values of -0.5, -0.25, -0.125, ... + localScaleFactor *= lineSearchCutFactor; + cumulativeScale += localScaleFactor; + + if( !checkWellSystemSolution( subRegion, dofManager, m_solution.values(), localScaleFactor ) ) + { + GEOS_LOG_LEVEL_RANK_0( logInfo::LineSearch, + GEOS_FMT( " Line search {}, solution check failed", lineSearchIteration ) ); + continue; + } + + + applyWellSystemSolution( dofManager, solution.values(), localScaleFactor, dt, domain, mesh, subRegion ); + // update non-primary variables (constitutive models) + + updateWellState( subRegion ); + // re-assemble system + localMatrix.zero(); + rhs.zero(); + + arrayView1d< real64 > const localRhs = rhs.open(); + + // call assemble to fill the matrix and the rhs + assembleWellSystem( time_n, + dt, + elemManager, + subRegion, + dofManager, + localMatrix, + localRhs ); + +// apply boundary conditions to system + applyWellBoundaryConditions( time_n, + dt, + elemManager, + subRegion, + dofManager, + localRhs, + localMatrix ); + + rhs.close(); + + GEOS_LOG_LEVEL_RANK_0( logInfo::LineSearch, + GEOS_FMT( " Line search @ {:0.3f}: ", cumulativeScale )); + + // get residual norm + residualNorm = calculateWellResidualNorm( time_n, dt, subRegion, dofManager, rhs.values() ); + GEOS_LOG_LEVEL_RANK_0( logInfo::LineSearch, + GEOS_FMT( " ( R ) = ( {:4.2e} )", residualNorm ) ); + + // if the residual norm is less than the last residual, we can proceed to the + // solution step + if( residualNorm < lastResidual ) + { + lineSearchSuccess = true; + break; + } + } + + lastResidual = residualNorm; + return lineSearchSuccess; +} + } // namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp index 3f8bc66d6a5..64fcf29c5b9 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp @@ -165,6 +165,15 @@ class WellSolverBase : public PhysicsSolverBase DomainPartition & domain ); + void setupWellDofs( DomainPartition & domain ); + + void setupWellSystem ( DomainPartition & domain, + DofManager & dofManager, + CRSMatrix< real64, globalIndex > & localMatrix, + ParallelVector & rhs, + ParallelVector & solution, + bool const setSparsity = true ); + virtual void setupDofs( DomainPartition const & domain, DofManager & dofManager ) const override; @@ -183,9 +192,34 @@ class WellSolverBase : public PhysicsSolverBase CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) override {} + virtual void applyWellBoundaryConditions( real64 const GEOS_UNUSED_PARAM( time_n ), + real64 const GEOS_UNUSED_PARAM( dt ), + ElementRegionManager & GEOS_UNUSED_PARAM( elemManager ), + WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ), + arrayView1d< real64 > const & GEOS_UNUSED_PARAM( localRhs ), + CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ) ) {} /**@}*/ + /** + * @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, @@ -327,6 +361,14 @@ class WellSolverBase : public PhysicsSolverBase MeshLevel & GEOS_UNUSED_PARAM( mesh ), WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ) ) = 0; + bool solveNonlinearSystem( real64 const & time_n, + real64 const & stepDt, + integer const cycleNumber, + DomainPartition & domain, + MeshLevel & mesh, + ElementRegionManager & elementRegionManager, + WellElementSubRegion & subregion, + DofManager const & dofManager ); /** * @brief Function to perform line search * @param time_n time at the beginning of the step @@ -431,8 +473,16 @@ class WellSolverBase : public PhysicsSolverBase real64 const & dt, DomainPartition & domain ) = 0; - virtual bool evaluateConstraints( real64 const & time_n, - WellElementSubRegion & subRegion ) = 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;}; + /// name of the flow solver @@ -470,8 +520,15 @@ class WellSolverBase : public PhysicsSolverBase integer m_estimateSolution; - integer m_useNewCode; + /// @brief DofManagers for each wells estimator + /// @details This DofManager is used to store the DOF numbers for the estimator + /// @note This DofManager is used in the assembly of the estimators linear system + std::map< std::string, DofManager > m_estimatorDoFManager; + + + integer m_useNewCode; + integer my_ctime; //tjb }; } diff --git a/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellKernels.hpp b/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellKernels.hpp index 5d106df3156..4532195a790 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellKernels.hpp @@ -329,7 +329,263 @@ class IsothermalCompositionalMultiPhaseFluxKernelFactory } }; +/** + * @class FaceBasedAssemblyKernel + * @tparam NUM_COMP number of fluid components + * @brief Define the interface for the assembly kernel in charge of flux terms + */ +template< integer NC, integer IS_THERMAL > +class IsothermalCompositionalMultiPhaseWellFluxKernel +{ +public: + + /// Compile time value for the number of components + static constexpr integer numComp = NC; + static constexpr integer resNumDOF = NC+1+IS_THERMAL; + + // Well jacobian column and row indicies + using WJ_COFFSET = compositionalMultiphaseWellKernels::ColOffset_WellJac< NC, IS_THERMAL >; + using WJ_ROFFSET = compositionalMultiphaseWellKernels::RowOffset_WellJac< NC, IS_THERMAL >; + + using ROFFSET = compositionalMultiphaseWellKernels::RowOffset; + using COFFSET = compositionalMultiphaseWellKernels::ColOffset; + + using CP_Deriv = multifluid::DerivativeOffsetC< NC, IS_THERMAL >; + + using TAG = compositionalMultiphaseWellKernels::SubRegionTag; + + + + /// Compute time value for the number of degrees of freedom + static constexpr integer numDof = WJ_COFFSET::nDer; + + /// Compile time value for the number of equations except volume and momentum + static constexpr integer numEqn = WJ_ROFFSET::nEqn - 2; + + /** + * @brief Constructor for the kernel interface + * @param[in] rankOffset the offset of my MPI rank + * @param[in] stencilWrapper reference to the stencil wrapper + * @param[in] dofNumberAccessor + * @param[in] compFlowAccessors + * @param[in] multiFluidAccessors + * @param[in] capPressureAccessors + * @param[in] permeabilityAccessors + * @param[in] dt time step size + * @param[inout] localMatrix the local CRS matrix + * @param[inout] localRhs the local right-hand side vector + * @param[in] kernelFlags flags packed together + */ + IsothermalCompositionalMultiPhaseWellFluxKernel( real64 const dt, + globalIndex const rankOffset, + string const wellDofKey, + WellElementSubRegion const & subRegion, + PerforationData const * const perforationData, + MultiFluidBase const & fluid, + arrayView1d< real64 > const & localRhs, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags ) + : + m_dt( dt ), + m_numPhases ( fluid.numFluidPhases()), + m_rankOffset( rankOffset ), + m_compPerfRate( perforationData->getField< fields::well::compPerforationRate >() ), + m_dCompPerfRate( perforationData->getField< fields::well::dCompPerforationRate >() ), + m_perfWellElemIndex( perforationData->getField< fields::perforation::wellElementIndex >() ), + m_wellElemDofNumber( subRegion.getReference< array1d< globalIndex > >( wellDofKey ) ), + m_localRhs( localRhs ), + m_localMatrix( localMatrix ), + m_useTotalMassEquation ( kernelFlags.isSet( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ) ) + { } + + + /** + * @brief Compute the local flux contributions to the residual and Jacobian + * @tparam FUNC the type of the function that can be used to customize the computation of the phase fluxes + * @param[in] ie the element index + * @param[inout] stack the stack variables + * @param[in] compFluxKernelOp the function used to customize the computation of the component fluxes + */ + + template< typename FUNC = NoOpFunc > + GEOS_HOST_DEVICE + inline + void computeFlux( localIndex const iperf, + FUNC && compFluxKernelOp = NoOpFunc{} ) const + { + + using namespace compositionalMultiphaseUtilities; + // local working variables and arrays + stackArray1d< localIndex, numComp > eqnRowIndices( numComp ); + stackArray1d< globalIndex, resNumDOF > dofColIndices( resNumDOF ); + + stackArray1d< real64, numComp > localPerf( numComp ); + stackArray2d< real64, numComp *resNumDOF > localPerfJacobian( numComp, resNumDOF ); + + // get the reservoir (sub)region and element indices + //localIndex const er = m_resElementRegion[iperf]; + //localIndex const esr = m_resElementSubRegion[iperf]; + //localIndex const ei = m_resElementIndex[iperf]; + + // get the well element index for this perforation + localIndex const iwelem = m_perfWellElemIndex[iperf]; + //globalIndex const resOffset = m_resElemDofNumber[er][esr][ei]; + globalIndex const wellElemOffset = m_wellElemDofNumber[iwelem]; + + for( integer ic = 0; ic < numComp; ++ic ) + { + eqnRowIndices[ ic] = LvArray::integerConversion< localIndex >( wellElemOffset - m_rankOffset ) + WJ_ROFFSET::MASSBAL + ic; + } + for( integer jdof = 0; jdof < NC+1; ++jdof ) + { + dofColIndices[ jdof] = wellElemOffset + WJ_COFFSET::dP + jdof; + } + // For temp its different + if constexpr ( IS_THERMAL ) + { + dofColIndices[ NC+1 ] = wellElemOffset + WJ_COFFSET::dT; + } + // populate local flux vector and derivatives + + for( integer ic = 0; ic < numComp; ++ic ) + { + localPerf[ic] = -m_dt * m_compPerfRate[iperf][ic]; + } + for( integer ic = 0; ic < numComp; ++ic ) + { + localIndex localDofIndexPres = 0; + + localPerfJacobian[ic][localDofIndexPres] = -m_dt * m_dCompPerfRate[iperf][TAG::WELL ][ic][CP_Deriv::dP]; + for( integer jc = 0; jc < numComp; ++jc ) + { + localIndex const localDofIndexComp = localDofIndexPres + jc + 1; + localPerfJacobian[ic][localDofIndexComp] = -m_dt * m_dCompPerfRate[iperf][TAG::WELL ][ic][CP_Deriv::dC+jc]; + } + if constexpr ( IS_THERMAL ) + { + localIndex localDofIndexTemp = localDofIndexPres + NC + 1; + localPerfJacobian[ic][localDofIndexTemp] = -m_dt * m_dCompPerfRate[iperf][TAG::WELL ][ic][CP_Deriv::dT]; + } + } + + if( m_useTotalMassEquation ) + { + stackArray1d< real64, resNumDOF > work( resNumDOF ); + shiftBlockRowsAheadByOneAndReplaceFirstRowWithColumnSum( numComp, numComp, resNumDOF, 1, localPerfJacobian, work ); + + // Apply equation/variable change transformation(s) + shiftBlockElementsAheadByOneAndReplaceFirstElementWithSum( numComp, numComp, 1, localPerf ); + } + + for( localIndex i = 0; i < localPerf.size(); ++i ) + { + if( eqnRowIndices[i] >= 0 && eqnRowIndices[i] < m_localMatrix.numRows() ) + { + m_localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( eqnRowIndices[i], + dofColIndices.data(), + localPerfJacobian[i].dataIfContiguous(), + resNumDOF ); + RAJA::atomicAdd( parallelDeviceAtomic{}, &m_localRhs[eqnRowIndices[i]], localPerf[i] ); + } + } + + compFluxKernelOp( wellElemOffset, iwelem, dofColIndices ); + + } + + +/** + * @brief Performs the kernel launch + * @tparam POLICY the policy used in the RAJA kernels + * @tparam KERNEL_TYPE the kernel type + * @param[in] numElements the number of elements + * @param[inout] kernelComponent the kernel component providing access to setup/compute/complete functions and stack + * variables + */ + template< typename POLICY, typename KERNEL_TYPE > + static void + launch( localIndex const numElements, + KERNEL_TYPE const & kernelComponent ) + { + GEOS_MARK_FUNCTION; + forAll< POLICY >( numElements, [=] GEOS_HOST_DEVICE ( localIndex const ie ) + { + kernelComponent.computeFlux( ie ); + + } ); + } + +protected: + +/// Time step size + real64 const m_dt; + +/// Number of phases + integer const m_numPhases; + + globalIndex const m_rankOffset; +// Perfoation variables + arrayView2d< real64 const > const m_compPerfRate; + arrayView4d< real64 const > const m_dCompPerfRate; + arrayView1d< localIndex const > const m_perfWellElemIndex; + +// Element region, subregion, index + arrayView1d< globalIndex const > const m_wellElemDofNumber; + +// RHS and Jacobian + arrayView1d< real64 > const m_localRhs; + CRSMatrixView< real64, globalIndex const > m_localMatrix; + + integer const m_useTotalMassEquation; +}; + +/** + * @class FaceBasedAssemblyKernelFactory + */ +class IsothermalCompositionalMultiPhaseWellFluxKernelFactory +{ +public: + + /** + * @brief Create a new kernel and launch + * @tparam POLICY the policy used in the RAJA kernel + * @param[in] numComps the number of fluid components + * @param[in] dt time step size + * @param[in] rankOffset the offset of my MPI rank + * @param[in] useTotalMassEquation flag specifying whether to replace one component bal eqn with total mass eqn + * @param[in] dofKey string to get the element degrees of freedom numbers + * @param[in] wellControls object holding well control/constraint information + * @param[in] subregion well subregion + * @param[inout] localMatrix the local CRS matrix + * @param[inout] localRhs the local right-hand side vector + */ + template< typename POLICY > + static void + createAndLaunch( integer const numComps, + real64 const dt, + globalIndex const rankOffset, + string const wellDofKey, + WellElementSubRegion const & subRegion, + PerforationData const * const perforationData, + MultiFluidBase const & fluid, + arrayView1d< real64 > const & localRhs, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags ) + { + isothermalCompositionalMultiphaseBaseKernels::internal::kernelLaunchSelectorCompSwitch( numComps, [&]( auto NC ) + { + integer constexpr NUM_COMP = NC(); + + using kernelType = IsothermalCompositionalMultiPhaseWellFluxKernel< NUM_COMP, 0 >; + kernelType kernel( dt, rankOffset, wellDofKey, subRegion, perforationData, + fluid, localRhs, localMatrix, kernelFlags ); + kernelType::template launch< POLICY >( perforationData->size(), kernel ); + } ); + + } +}; +/********************************************************/ /** * @class FaceBasedAssemblyKernel * @tparam NUM_COMP number of fluid components @@ -441,7 +697,7 @@ class ThermalCompositionalMultiPhaseFluxKernel : public IsothermalCompositionalM return; } // local working variables and arrays - stackArray1d< localIndex, 2* numComp > eqnRowIndices( 2 ); + stackArray1d< localIndex, 2* numComp > eqnRowIndices( 2* numComp ); stackArray1d< real64, 2 * numComp > localPerf( 2 ); stackArray2d< real64, 2 * resNumDOF * 2 * numComp > localPerfJacobian( 2, 2 * resNumDOF ); @@ -573,6 +829,225 @@ class ThermalCompositionalMultiPhaseFluxKernelFactory } }; +/********************************************************/ +/** + * @class FaceBasedAssemblyKernel + * @tparam NUM_COMP number of fluid components + * @brief Define the interface for the assembly kernel in charge of flux terms + */ +template< integer NC, integer IS_THERMAL > +class ThermalCompositionalMultiPhaseWellFluxKernel : public IsothermalCompositionalMultiPhaseWellFluxKernel< NC, IS_THERMAL > +{ +public: + using Base = IsothermalCompositionalMultiPhaseWellFluxKernel< NC, IS_THERMAL >; + /// Compile time value for the number of components + static constexpr integer numComp = NC; + static constexpr integer resNumDOF = NC+1+IS_THERMAL; + + // Well jacobian column and row indicies + using WJ_COFFSET = compositionalMultiphaseWellKernels::ColOffset_WellJac< NC, IS_THERMAL >; + using WJ_ROFFSET = compositionalMultiphaseWellKernels::RowOffset_WellJac< NC, IS_THERMAL >; + + using ROFFSET = compositionalMultiphaseWellKernels::RowOffset; + using COFFSET = compositionalMultiphaseWellKernels::ColOffset; + + using CP_Deriv = multifluid::DerivativeOffsetC< NC, IS_THERMAL >; + + using TAG = compositionalMultiphaseWellKernels::SubRegionTag; + + using Base::m_dt; + using Base::m_localRhs; + using Base::m_localMatrix; + using Base::m_rankOffset; + + + + /// Compute time value for the number of degrees of freedom + static constexpr integer numDof = WJ_COFFSET::nDer; + + /// Compile time value for the number of equations except volume and momentum + static constexpr integer numEqn = WJ_ROFFSET::nEqn - 2; + + /** + * @brief Constructor for the kernel interface + * @param[in] rankOffset the offset of my MPI rank + * @param[in] stencilWrapper reference to the stencil wrapper + * @param[in] dofNumberAccessor + * @param[in] compFlowAccessors + * @param[in] multiFluidAccessors + * @param[in] capPressureAccessors + * @param[in] permeabilityAccessors + * @param[in] dt time step size + * @param[inout] localMatrix the local CRS matrix + * @param[inout] localRhs the local right-hand side vector + * @param[in] kernelFlags flags packed together + */ + ThermalCompositionalMultiPhaseWellFluxKernel( real64 const dt, + integer const isProducer, + globalIndex const rankOffset, + string const wellDofKey, + WellElementSubRegion const & subRegion, + PerforationData const * const perforationData, + MultiFluidBase const & fluid, + arrayView1d< real64 > const & localRhs, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags ) + : Base( dt, + rankOffset, + wellDofKey, + subRegion, + perforationData, + fluid, + localRhs, + localMatrix, + kernelFlags ), + m_isProducer( isProducer ), + m_globalWellElementIndex( subRegion.getGlobalWellElementIndex() ), + m_energyPerfFlux( perforationData->getField< fields::well::energyPerforationFlux >()), + m_dEnergyPerfFlux( perforationData->getField< fields::well::dEnergyPerforationFlux >()) + + { } + + + /** + * @brief Compute the local flux contributions to the residual and Jacobian + * @tparam FUNC the type of the function that can be used to customize the computation of the phase fluxes + * @param[in] ie the element index + * @param[inout] stack the stack variables + * @param[in] compFluxKernelOp the function used to customize the computation of the component fluxes + */ + + GEOS_HOST_DEVICE + inline + void computeFlux( localIndex const iperf ) const + { + Base::computeFlux( iperf, [&] ( globalIndex const & wellElemOffset, + localIndex const iwelem, + stackArray1d< globalIndex, resNumDOF > & dofColIndices ) + { + // No energy equation if top element and Injector + // Top element defined by global index == 0 + // Assumption is global index == 0 is top segment with fixed temp BC + if( !m_isProducer ) + { + if( m_globalWellElementIndex[iwelem] == 0 ) + return; + } + // local working variables and arrays + localIndex eqnRowIndices = LvArray::integerConversion< localIndex >( wellElemOffset - m_rankOffset ) + WJ_ROFFSET::ENERGYBAL; + + stackArray2d< real64, resNumDOF > localPerfJacobian( 1, resNumDOF ); + // populate local flux vector and derivatives + + real64 localPerf = -m_dt * m_energyPerfFlux[iperf]; + + localIndex localDofIndexPres = 0; + localPerfJacobian [0][localDofIndexPres] = -m_dt * m_dEnergyPerfFlux[iperf][TAG::WELL][CP_Deriv::dP]; + + // populate local flux vector and derivatives + for( integer ic = 0; ic < numComp; ++ic ) + { + localIndex const localDofIndexComp = localDofIndexPres + ic + 1; + localPerfJacobian [0][localDofIndexComp] = -m_dt * m_dEnergyPerfFlux[iperf][TAG::WELL ][CP_Deriv::dC+ic]; + } + localPerfJacobian [0][localDofIndexPres+NC+1] = -m_dt * m_dEnergyPerfFlux[iperf][TAG::WELL ][CP_Deriv::dT]; + + if( eqnRowIndices >= 0 && eqnRowIndices < m_localMatrix.numRows() ) + { + m_localMatrix.template addToRowBinarySearchUnsorted< parallelDeviceAtomic >( eqnRowIndices, + dofColIndices.data(), + localPerfJacobian[0].dataIfContiguous(), + resNumDOF ); + RAJA::atomicAdd( parallelDeviceAtomic{}, &m_localRhs[eqnRowIndices], localPerf ); + } + } ); + + + } + + + /** + * @brief Performs the kernel launch + * @tparam POLICY the policy used in the RAJA kernels + * @tparam KERNEL_TYPE the kernel type + * @param[in] numElements the number of elements + * @param[inout] kernelComponent the kernel component providing access to setup/compute/complete functions and stack + * variables + */ + template< typename POLICY, typename KERNEL_TYPE > + static void + launch( localIndex const numElements, + KERNEL_TYPE const & kernelComponent ) + { + GEOS_MARK_FUNCTION; + forAll< POLICY >( numElements, [=] GEOS_HOST_DEVICE ( localIndex const ie ) + { + kernelComponent.computeFlux( ie ); + + } ); + } + +protected: + + /// Well type + integer const m_isProducer; + + /// Global index of local element + arrayView1d< globalIndex const > m_globalWellElementIndex; + + /// Views on energy flux + arrayView1d< real64 const > const m_energyPerfFlux; + arrayView3d< real64 const > const m_dEnergyPerfFlux; +}; + +/** + * @class ThermalCompositionalMultiPhaseFluxWellKernelFactory + */ +class ThermalCompositionalMultiPhaseWellFluxKernelFactory +{ +public: + + /** + * @brief Create a new kernel and launch + * @tparam POLICY the policy used in the RAJA kernel + * @param[in] numComps the number of fluid components + * @param[in] dt time step size + * @param[in] rankOffset the offset of my MPI rank + * @param[in] useTotalMassEquation flag specifying whether to replace one component bal eqn with total mass eqn + * @param[in] dofKey string to get the element degrees of freedom numbers + * @param[in] wellControls object holding well control/constraint information + * @param[in] subregion well subregion + * @param[inout] localMatrix the local CRS matrix + * @param[inout] localRhs the local right-hand side vector + */ + template< typename POLICY > + static void + createAndLaunch( integer const numComps, + integer const isProducer, + real64 const dt, + globalIndex const rankOffset, + string const wellDofKey, + WellElementSubRegion const & subRegion, + PerforationData const * const perforationData, + MultiFluidBase const & fluid, + BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags, + arrayView1d< real64 > const & localRhs, + CRSMatrixView< real64, globalIndex const > const & localMatrix + ) + { + isothermalCompositionalMultiphaseBaseKernels::internal::kernelLaunchSelectorCompSwitch( numComps, [&]( auto NC ) + { + integer constexpr NUM_COMP = NC(); + + using kernelType = ThermalCompositionalMultiPhaseWellFluxKernel< NUM_COMP, 1 >; + kernelType kernel( dt, isProducer, rankOffset, wellDofKey, subRegion, perforationData, + fluid, localRhs, localMatrix, kernelFlags ); + kernelType::template launch< POLICY >( perforationData->size(), kernel ); + } ); + + } +}; + } // end namespace coupledReservoirAndWellKernels } // end namespace geos From 292c90f6ba9f5fa3c4711a6a67a25fde37310050 Mon Sep 17 00:00:00 2001 From: Thomas James Byer Date: Wed, 15 Oct 2025 09:38:31 -0700 Subject: [PATCH 14/41] 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 15/41] 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 16/41] 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 17/41] 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 18/41] 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 19/41] 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 20/41] 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 21/41] 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 22/41] 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 23/41] 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 24/41] 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 25/41] 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 26/41] 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 27/41] 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 28/41] 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 29/41] 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 30/41] 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 31/41] 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: Sat, 1 Nov 2025 09:21:22 -0700 Subject: [PATCH 32/41] ... --- .../wellsTests/CMakeLists.txt | 2 + .../testThermalEstimatorInjWell.cpp | 1003 +++++++++++++++++ .../testThermalEstimatorProdWell.cpp | 1002 ++++++++++++++++ .../wells/CompositionalMultiphaseWell.cpp | 688 ++++++++++- .../wells/CompositionalMultiphaseWell.hpp | 48 +- .../fluidFlow/wells/SinglePhaseWell.cpp | 66 +- .../fluidFlow/wells/SinglePhaseWell.hpp | 27 +- .../fluidFlow/wells/WellConstraintsBase.cpp | 9 +- .../fluidFlow/wells/WellConstraintsBase.hpp | 4 +- .../fluidFlow/wells/WellControls.cpp | 37 +- .../fluidFlow/wells/WellControls.hpp | 26 +- .../fluidFlow/wells/WellPropWriter.hpp | 609 ++++++++++ .../fluidFlow/wells/WellSolverBase.cpp | 163 ++- .../fluidFlow/wells/WellSolverBase.hpp | 63 +- .../CompositionalMultiphaseWellKernels.cpp | 58 +- .../CompositionalMultiphaseWellKernels.hpp | 19 +- .../wells/kernels/PerforationFluxKernels.hpp | 171 ++- ...rmalCompositionalMultiphaseWellKernels.hpp | 48 +- .../CoupledReservoirAndWellKernels.hpp | 5 +- src/coreComponents/schema/schema.xsd | 93 +- src/coreComponents/schema/schema.xsd.other | 54 +- src/main/main.cpp | 36 + 22 files changed, 3911 insertions(+), 320 deletions(-) create mode 100644 src/coreComponents/integrationTests/wellsTests/testThermalEstimatorInjWell.cpp create mode 100644 src/coreComponents/integrationTests/wellsTests/testThermalEstimatorProdWell.cpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/wells/WellPropWriter.hpp diff --git a/src/coreComponents/integrationTests/wellsTests/CMakeLists.txt b/src/coreComponents/integrationTests/wellsTests/CMakeLists.txt index 5a30f2fe376..4aad90f9655 100644 --- a/src/coreComponents/integrationTests/wellsTests/CMakeLists.txt +++ b/src/coreComponents/integrationTests/wellsTests/CMakeLists.txt @@ -9,6 +9,8 @@ set( dependencyList mainInterface ) if( ENABLE_PVTPackage ) list( APPEND gtest_geosx_tests testOpenClosePerf.cpp + testThermalEstimatorProdWell.cpp + testThermalEstimatorInjWell.cpp testReservoirCompositionalMultiphaseMSWells.cpp testReservoirThermalSinglePhaseMSWells.cpp testReservoirThermalSinglePhaseMSWells_RateInj.cpp diff --git a/src/coreComponents/integrationTests/wellsTests/testThermalEstimatorInjWell.cpp b/src/coreComponents/integrationTests/wellsTests/testThermalEstimatorInjWell.cpp new file mode 100644 index 00000000000..12903f077f6 --- /dev/null +++ b/src/coreComponents/integrationTests/wellsTests/testThermalEstimatorInjWell.cpp @@ -0,0 +1,1003 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +#include "integrationTests/fluidFlowTests/testCompFlowUtils.hpp" + +#include "common/DataTypes.hpp" +#include "mainInterface/initialization.hpp" +#include "constitutive/fluid/multifluid/MultiFluidBase.hpp" +#include "mainInterface/ProblemManager.hpp" +#include "mesh/DomainPartition.hpp" +#include "mainInterface/GeosxState.hpp" +#include "mesh/WellElementSubRegion.hpp" +#include "physicsSolvers/PhysicsSolverManager.hpp" +#include "physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.hpp" +#include "physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.hpp" +#include "physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp" +#include "physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWellFields.hpp" +#include "physicsSolvers/fluidFlow/wells/WellSolverBaseFields.hpp" +#include "physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp" + +using namespace geos; +using namespace geos::dataRepository; +using namespace geos::constitutive; +using namespace geos::testing; + +CommandLineOptions g_commandLineOptions; + +void writeTableToFile( string const & filename, char const * str ) +{ + std::ofstream os( filename ); + ASSERT_TRUE( os.is_open() ); + os << str; + os.close(); +} + +void removeFile( string const & filename ) +{ + int const ret = std::remove( filename.c_str() ); + ASSERT_TRUE( ret == 0 ); +} +char const * co2flash = "FlashModel CO2Solubility 1e5 7.5e7 5e5 283.15 414.15 10 0\n"; +char const * pvtLiquid = "DensityFun PhillipsBrineDensity 1e5 7.5e7 5e5 283.15 414.15 10 0\n" + "ViscosityFun PhillipsBrineViscosity 0\n" + "EnthalpyFun BrineEnthalpy 1e5 7.5e7 5e5 283.15 414.15 10 0\n"; + +char const * pvtGas = "DensityFun SpanWagnerCO2Density 1e5 7.5e7 5e5 283.15 414.15 10\n" + "ViscosityFun FenghourCO2Viscosity 1e5 7.5e7 5e5 283.15 414.15 10\n" + "EnthalpyFun CO2Enthalpy 1e5 7.5e7 5e5 283.15 414.15 10\n"; +char const * xmlInput = + R"xml( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +)xml"; + +template< typename T, typename COL_INDEX > +void printCompareLocalMatrices( CRSMatrixView< T const, COL_INDEX const > const & matrix1, + CRSMatrixView< T const, COL_INDEX const > const & matrix2, std::string const & testName ) +{ + std::ofstream omat1( testName+".csv" ); + + + std::vector< std::vector< double > > fmat1( matrix1.numRows(), std::vector< double >( matrix1.numRows(), 0.0 )); + std::vector< std::vector< double > > fmat2( matrix2.numRows(), std::vector< double >( matrix2.numRows(), 0.0 )); + + for( localIndex i = 0; i < matrix1.numRows(); ++i ) + { + arraySlice1d< globalIndex const > indices1 = matrix1.getColumns( i ); + arraySlice1d< globalIndex const > indices2 = matrix2.getColumns( i ); + arraySlice1d< double const > values1 = matrix1.getEntries( i ); + arraySlice1d< double const > values2 = matrix2.getEntries( i ); + for( integer j=0; j const & rsd1, + array1d< real64 > const & rsd2, std::string const & testName ) +{ + std::ofstream omat1( testName+".csv" ); + + for( integer i=0; i +void testWellEstimatorNumericalJacobian( CompositionalMultiphaseReservoirAndWells< CompositionalMultiphaseBase > & solver, + DomainPartition & domain, + real64 const perturbParameter, + real64 const time_n, + real64 const relTol, std::string const & testName, + LAMBDA && assembleFunction ) +{ + CompositionalMultiphaseWell & wellSolver = *solver.wellSolver(); + CompositionalMultiphaseFVM & flowSolver = dynamicCast< CompositionalMultiphaseFVM & >( *solver.reservoirSolver() ); + + localIndex const NC = flowSolver.numFluidComponents(); + + CRSMatrix< real64, globalIndex > const & jacobian = wellSolver.getLocalMatrix(); + array1d< real64 > residual( jacobian.numRows() ); + DofManager const & dofManager = wellSolver.getDofManager(); + + // assemble the analytical residual + solver.resetStateToBeginningOfStep( domain ); + + residual.zero(); + jacobian.zero(); + + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.setWellState( 1 ); + wellSolver.initializeWell( domain, mesh, subRegion, time_n ); + } ); + } ); + + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + residual.move( hostMemorySpace, false ); + + // copy the analytical residual + array1d< real64 > residualOrig( residual ); + + // create the numerical jacobian + jacobian.move( hostMemorySpace ); + CRSMatrix< real64, globalIndex > jacobianFD( jacobian ); + jacobianFD.zero(); + + + string const wellDofKey = dofManager.getKey( wellSolver.wellElementDofName() ); + + // at this point we start assembling the finite-difference block by block + + + ///////////////////////////////////////////////// + // Step 2) Compute the terms in J_RW and J_WW // + ///////////////////////////////////////////////// + + // loop over the wells + if( 1 ) + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + // get the degrees of freedom, ghosting info and next well elem index + arrayView1d< globalIndex const > const & wellElemDofNumber = + subRegion.getReference< array1d< globalIndex > >( wellDofKey ); + + // get the primary variables on the well elements + arrayView1d< real64 > const & wellElemPressure = + subRegion.getField< fields::well::pressure >(); + wellElemPressure.move( hostMemorySpace, false ); + + arrayView1d< real64 > const & wellElemTemperature = + subRegion.getField< fields::well::temperature >(); + wellElemTemperature.move( hostMemorySpace, false ); + + arrayView2d< real64, compflow::USD_COMP > const & wellElemCompDens = + subRegion.getField< fields::well::globalCompDensity >(); + wellElemCompDens.move( hostMemorySpace, false ); + + arrayView1d< real64 > const & connRate = + subRegion.getField< fields::well::mixtureConnectionRate >(); + connRate.move( hostMemorySpace, false ); + + // a) compute all the derivatives wrt to the pressure in WELL elem iwelem + for( localIndex iwelem = 0; iwelem < subRegion.size(); ++iwelem ) + { + + real64 wellElemTotalDensity = 0.0; + for( localIndex ic = 0; ic < NC; ++ic ) + { + wellElemTotalDensity += wellElemCompDens[iwelem][ic]; + } + + { + solver.resetStateToBeginningOfStep( domain ); + + // here is the perturbation in the pressure of the well element + 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 ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + wellElemDofNumber[iwelem] + compositionalMultiphaseWellKernels::ColOffset::DPRES, + dP, + jacobianFD.toViewConstSizes() ); + } + + for( localIndex jc = 0; jc < NC; ++jc ) + { + solver.resetStateToBeginningOfStep( domain ); + + real64 const dRho = perturbParameter * wellElemTotalDensity; + wellElemCompDens.move( hostMemorySpace, true ); + wellElemCompDens[iwelem][jc] += dRho; + + wellSolver.updateState( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + wellElemDofNumber[iwelem] + compositionalMultiphaseWellKernels::ColOffset::DCOMP + jc, + dRho, + jacobianFD.toViewConstSizes() ); + } + { + solver.resetStateToBeginningOfStep( domain ); + residual.zero(); + jacobian.zero(); + // here is the perturbation in the temperature of the well element + real64 const dT = perturbParameter * ( wellElemTemperature[iwelem] + perturbParameter ); + wellElemTemperature.move( hostMemorySpace, true ); + wellElemTemperature[iwelem] += dT; + + // after perturbing, update the pressure-dependent quantities in the well + wellSolver.updateState( domain ); + + + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + wellElemDofNumber[iwelem] + compositionalMultiphaseWellKernels::ColOffset::DCOMP + NC+1, + dT, + jacobianFD.toViewConstSizes() ); + + } + } + + + // b) compute all the derivatives wrt to the connection in WELL elem + // iwelem + for( localIndex iwelem = 0; iwelem < subRegion.size(); ++iwelem ) + { + { + solver.resetStateToBeginningOfStep( domain ); + + // here is the perturbation in the rate of the well element + real64 const dRate = perturbParameter * ( connRate[iwelem] + perturbParameter ); + connRate.move( hostMemorySpace, true ); + connRate[iwelem] += dRate; + + wellSolver.updateState( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + wellElemDofNumber[iwelem] + compositionalMultiphaseWellKernels::ColOffset::DCOMP + NC, + dRate, + jacobianFD.toViewConstSizes() ); + } + } + } ); + } ); + + // assemble the analytical jacobian + solver.resetStateToBeginningOfStep( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + printCompareLocalMatrices( jacobian.toViewConst(), jacobianFD.toViewConst(), testName ); + compareLocalMatrices( jacobian.toViewConst(), jacobianFD.toViewConst(), relTol ); +} +template< typename LAMBDA > +void testNumericalJacobian( CompositionalMultiphaseReservoirAndWells< CompositionalMultiphaseBase > & solver, + DomainPartition & domain, + real64 const perturbParameter, + real64 const relTol, std::string const & testName, + LAMBDA && assembleFunction ) +{ + CompositionalMultiphaseWell & wellSolver = *solver.wellSolver(); + CompositionalMultiphaseFVM & flowSolver = dynamicCast< CompositionalMultiphaseFVM & >( *solver.reservoirSolver() ); + + localIndex const NC = flowSolver.numFluidComponents(); + + CRSMatrix< real64, globalIndex > const & jacobian = solver.getLocalMatrix(); + array1d< real64 > residual( jacobian.numRows() ); + DofManager const & dofManager = solver.getDofManager(); + + // assemble the analytical residual + solver.resetStateToBeginningOfStep( domain ); + + residual.zero(); + jacobian.zero(); + + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + residual.move( hostMemorySpace, false ); + + // copy the analytical residual + array1d< real64 > residualOrig( residual ); + + // create the numerical jacobian + jacobian.move( hostMemorySpace ); + CRSMatrix< real64, globalIndex > jacobianFD( jacobian ); + jacobianFD.zero(); + + string const resDofKey = dofManager.getKey( wellSolver.resElementDofName() ); + string const wellDofKey = dofManager.getKey( wellSolver.wellElementDofName() ); + + // at this point we start assembling the finite-difference block by block + + //////////////////////////////////////////////// + // Step 1) Compute the terms in J_RR and J_WR // + //////////////////////////////////////////////// + if( 1 ) + domain.forMeshBodies( [&] ( MeshBody & meshBody ) + { + meshBody.forMeshLevels( [&] ( MeshLevel & mesh ) + { + ElementRegionManager & elemManager = mesh.getElemManager(); + for( localIndex er = 0; er < elemManager.numRegions(); ++er ) + { + ElementRegionBase & elemRegion = elemManager.getRegion( er ); + elemRegion.forElementSubRegionsIndex< CellElementSubRegion >( [&]( localIndex const, CellElementSubRegion & subRegion ) + { + // get the degrees of freedom and ghosting information + arrayView1d< globalIndex const > const & dofNumber = + subRegion.getReference< array1d< globalIndex > >( resDofKey ); + + // get the primary variables on the reservoir elements + arrayView1d< real64 > const & pres = + subRegion.getField< fields::flow::pressure >(); + pres.move( hostMemorySpace, false ); + + arrayView2d< real64, compflow::USD_COMP > const & compDens = + subRegion.getField< fields::flow::globalCompDensity >(); + compDens.move( hostMemorySpace, false ); + + arrayView1d< real64 > const & temp = + subRegion.getField< fields::flow::temperature >(); + temp.move( hostMemorySpace, false ); + + // a) compute all the derivatives wrt to the pressure in RESERVOIR elem ei + for( localIndex ei = 0; ei < subRegion.size(); ++ei ) + { + real64 totalDensity = 0.0; + for( localIndex ic = 0; ic < NC; ++ic ) + { + totalDensity += compDens[ei][ic]; + } + + { + solver.resetStateToBeginningOfStep( domain ); + + // here is the perturbation in the pressure of the element + real64 const dP = perturbParameter * (pres[ei] + perturbParameter); + pres.move( hostMemorySpace, true ); + pres[ei] += dP; + + // after perturbing, update the pressure-dependent quantities in the reservoir + flowSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh2, + string_array const & regionNames2 ) + { + mesh2.getElemManager().forElementSubRegions( regionNames2, + [&]( localIndex const, + ElementSubRegionBase & subRegion2 ) + { + flowSolver.updateFluidState( subRegion2 ); + } ); + } ); + + wellSolver.updateState( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + dofNumber[ei], + dP, + jacobianFD.toViewConstSizes() ); + } + + for( localIndex jc = 0; jc < NC; ++jc ) + { + solver.resetStateToBeginningOfStep( domain ); + + real64 const dRho = perturbParameter * totalDensity; + compDens.move( hostMemorySpace, true ); + compDens[ei][jc] += dRho; + + flowSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh2, + string_array const & regionNames2 ) + { + mesh2.getElemManager().forElementSubRegions( regionNames2, + [&]( localIndex const, + ElementSubRegionBase & subRegion2 ) + { + flowSolver.updateFluidState( subRegion2 ); + } ); + } ); + wellSolver.updateState( domain ); + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + dofNumber[ei] + jc + 1, + dRho, + jacobianFD.toViewConstSizes() ); + } + { + solver.resetStateToBeginningOfStep( domain ); + + // here is the perturbation in the pressure of the element + real64 const dTemp = perturbParameter * (temp[ei] + perturbParameter); + temp.move( hostMemorySpace, true ); + temp[ei] += dTemp; + + // after perturbing, update the pressure-dependent quantities in the reservoir + flowSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh2, + string_array const & regionNames2 ) + { + mesh2.getElemManager().forElementSubRegions( regionNames2, + [&]( localIndex const, + ElementSubRegionBase & subRegion2 ) + { + flowSolver.updateFluidState( subRegion2 ); + } ); + } ); + + wellSolver.updateState( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + dofNumber[ei]+NC+1, + dTemp, + jacobianFD.toViewConstSizes() ); + } + } + } ); + } + } ); + + } ); + + ///////////////////////////////////////////////// + // Step 2) Compute the terms in J_RW and J_WW // + ///////////////////////////////////////////////// + + // loop over the wells + if( 1 ) + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + // get the degrees of freedom, ghosting info and next well elem index + arrayView1d< globalIndex const > const & wellElemDofNumber = + subRegion.getReference< array1d< globalIndex > >( wellDofKey ); + + // get the primary variables on the well elements + arrayView1d< real64 > const & wellElemPressure = + subRegion.getField< fields::well::pressure >(); + wellElemPressure.move( hostMemorySpace, false ); + + arrayView1d< real64 > const & wellElemTemperature = + subRegion.getField< fields::well::temperature >(); + wellElemTemperature.move( hostMemorySpace, false ); + + arrayView2d< real64, compflow::USD_COMP > const & wellElemCompDens = + subRegion.getField< fields::well::globalCompDensity >(); + wellElemCompDens.move( hostMemorySpace, false ); + + arrayView1d< real64 > const & connRate = + subRegion.getField< fields::well::mixtureConnectionRate >(); + connRate.move( hostMemorySpace, false ); + + // a) compute all the derivatives wrt to the pressure in WELL elem iwelem + for( localIndex iwelem = 0; iwelem < subRegion.size(); ++iwelem ) + { + + real64 wellElemTotalDensity = 0.0; + for( localIndex ic = 0; ic < NC; ++ic ) + { + wellElemTotalDensity += wellElemCompDens[iwelem][ic]; + } + + { + solver.resetStateToBeginningOfStep( domain ); + + // here is the perturbation in the pressure of the well element + 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 ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + wellElemDofNumber[iwelem] + compositionalMultiphaseWellKernels::ColOffset::DPRES, + dP, + jacobianFD.toViewConstSizes() ); + } + + for( localIndex jc = 0; jc < NC; ++jc ) + { + solver.resetStateToBeginningOfStep( domain ); + + real64 const dRho = perturbParameter * wellElemTotalDensity; + wellElemCompDens.move( hostMemorySpace, true ); + wellElemCompDens[iwelem][jc] += dRho; + + wellSolver.updateState( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + wellElemDofNumber[iwelem] + compositionalMultiphaseWellKernels::ColOffset::DCOMP + jc, + dRho, + jacobianFD.toViewConstSizes() ); + } + { + solver.resetStateToBeginningOfStep( domain ); + residual.zero(); + jacobian.zero(); + // here is the perturbation in the temperature of the well element + real64 const dT = perturbParameter * ( wellElemTemperature[iwelem] + perturbParameter ); + wellElemTemperature.move( hostMemorySpace, true ); + wellElemTemperature[iwelem] += dT; + + // after perturbing, update the pressure-dependent quantities in the well + wellSolver.updateState( domain ); + + + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + wellElemDofNumber[iwelem] + compositionalMultiphaseWellKernels::ColOffset::DCOMP + NC+1, + dT, + jacobianFD.toViewConstSizes() ); + + } + } + + + // b) compute all the derivatives wrt to the connection in WELL elem + // iwelem + for( localIndex iwelem = 0; iwelem < subRegion.size(); ++iwelem ) + { + { + solver.resetStateToBeginningOfStep( domain ); + + // here is the perturbation in the rate of the well element + real64 const dRate = perturbParameter * ( connRate[iwelem] + perturbParameter ); + connRate.move( hostMemorySpace, true ); + connRate[iwelem] += dRate; + + wellSolver.updateState( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + wellElemDofNumber[iwelem] + compositionalMultiphaseWellKernels::ColOffset::DCOMP + NC, + dRate, + jacobianFD.toViewConstSizes() ); + } + } + } ); + } ); + + // assemble the analytical jacobian + solver.resetStateToBeginningOfStep( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + printCompareLocalMatrices( jacobian.toViewConst(), jacobianFD.toViewConst(), testName ); + compareLocalMatrices( jacobian.toViewConst(), jacobianFD.toViewConst(), relTol ); +} + +class CompositionalMultiphaseReservoirSolverTest : public ::testing::Test +{ +public: + + CompositionalMultiphaseReservoirSolverTest(): + state( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ) + {} + +protected: + + void SetUp() override + { + setupProblemFromXML( state.getProblemManager(), xmlInput ); + solver = &state.getProblemManager().getPhysicsSolverManager().getGroup< CompositionalMultiphaseReservoirAndWells< CompositionalMultiphaseBase > >( "reservoirSystem" ); + + DomainPartition & domain = state.getProblemManager().getDomainPartition(); + + solver->setupSystem( domain, + solver->getDofManager(), + solver->getLocalMatrix(), + solver->getSystemRhs(), + solver->getSystemSolution() ); + + solver->wellSolver()->setupSystem( domain, + solver->wellSolver()->getDofManager(), + solver->wellSolver()->getLocalMatrix(), + solver->wellSolver()->getSystemRhs(), + solver->wellSolver()->getSystemSolution() ); + + solver->implicitStepSetup( time, dt, domain ); + + } + + static real64 constexpr time = 0.0; + static real64 constexpr dt = 1e4; + static real64 constexpr eps = std::numeric_limits< real64 >::epsilon(); + + GeosxState state; + CompositionalMultiphaseReservoirAndWells< CompositionalMultiphaseBase > * solver; +}; + +real64 constexpr CompositionalMultiphaseReservoirSolverTest::time; +real64 constexpr CompositionalMultiphaseReservoirSolverTest::dt; +real64 constexpr CompositionalMultiphaseReservoirSolverTest::eps; + + +TEST_F( CompositionalMultiphaseReservoirSolverTest, jacobianNumericalCheck_Perforation ) +{ + real64 const perturb = std::sqrt( eps ); + real64 const tol = 1e-1; // 10% error margin + + DomainPartition & domain = state.getProblemManager().getDomainPartition(); + + testWellEstimatorNumericalJacobian( *solver, domain, perturb, time, tol, "WellEstimator", + [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) + { + + DofManager const & dofManager = solver->wellSolver()->getDofManager(); + solver->wellSolver()->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + ElementRegionManager & elemManager = mesh.getElemManager(); + elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + // call assemble to fill the matrix and the rhs + solver->wellSolver()->assembleWellSystem( time, + dt, + elemManager, + subRegion, + dofManager, + localMatrix, + localRhs ); + +// apply boundary conditions to system + + solver->wellSolver()->applyWellBoundaryConditions( time, + dt, + elemManager, + subRegion, + dofManager, + localRhs, + localMatrix ); + + solver->wellSolver()->outputSingleWellDebug( time, dt, 0, 0, 0, mesh, subRegion, dofManager, localMatrix, localRhs ); + } ); + } ); + + + + } ); +} + + +int main( int argc, char * * argv ) +{ + writeTableToFile( "co2flash.txt", co2flash ); + writeTableToFile( "pvtliquid.txt", pvtLiquid ); + writeTableToFile( "pvtgas.txt", pvtGas ); + ::testing::InitGoogleTest( &argc, argv ); + g_commandLineOptions = *geos::basicSetup( argc, argv ); + int const result = RUN_ALL_TESTS(); + geos::basicCleanup(); + removeFile( "co2flash.txt" ); + removeFile( "pvtliquid.txt" ); + removeFile( "pvtgas.txt" ); + + return result; +} diff --git a/src/coreComponents/integrationTests/wellsTests/testThermalEstimatorProdWell.cpp b/src/coreComponents/integrationTests/wellsTests/testThermalEstimatorProdWell.cpp new file mode 100644 index 00000000000..8ef86902c2d --- /dev/null +++ b/src/coreComponents/integrationTests/wellsTests/testThermalEstimatorProdWell.cpp @@ -0,0 +1,1002 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +#include "integrationTests/fluidFlowTests/testCompFlowUtils.hpp" + +#include "common/DataTypes.hpp" +#include "mainInterface/initialization.hpp" +#include "constitutive/fluid/multifluid/MultiFluidBase.hpp" +#include "mainInterface/ProblemManager.hpp" +#include "mesh/DomainPartition.hpp" +#include "mainInterface/GeosxState.hpp" +#include "mesh/WellElementSubRegion.hpp" +#include "physicsSolvers/PhysicsSolverManager.hpp" +#include "physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.hpp" +#include "physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.hpp" +#include "physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp" +#include "physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWellFields.hpp" +#include "physicsSolvers/fluidFlow/wells/WellSolverBaseFields.hpp" +#include "physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp" + +using namespace geos; +using namespace geos::dataRepository; +using namespace geos::constitutive; +using namespace geos::testing; + +CommandLineOptions g_commandLineOptions; + +void writeTableToFile( string const & filename, char const * str ) +{ + std::ofstream os( filename ); + ASSERT_TRUE( os.is_open() ); + os << str; + os.close(); +} + +void removeFile( string const & filename ) +{ + int const ret = std::remove( filename.c_str() ); + ASSERT_TRUE( ret == 0 ); +} +char const * co2flash = "FlashModel CO2Solubility 1e5 7.5e7 5e5 283.15 414.15 10 0\n"; +char const * pvtLiquid = "DensityFun PhillipsBrineDensity 1e5 7.5e7 5e5 283.15 414.15 10 0\n" + "ViscosityFun PhillipsBrineViscosity 0\n" + "EnthalpyFun BrineEnthalpy 1e5 7.5e7 5e5 283.15 414.15 10 0\n"; + +char const * pvtGas = "DensityFun SpanWagnerCO2Density 1e5 7.5e7 5e5 283.15 414.15 10\n" + "ViscosityFun FenghourCO2Viscosity 1e5 7.5e7 5e5 283.15 414.15 10\n" + "EnthalpyFun CO2Enthalpy 1e5 7.5e7 5e5 283.15 414.15 10\n"; +char const * xmlInput = + R"xml( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +)xml"; + +template< typename T, typename COL_INDEX > +void printCompareLocalMatrices( CRSMatrixView< T const, COL_INDEX const > const & matrix1, + CRSMatrixView< T const, COL_INDEX const > const & matrix2, std::string const & testName ) +{ + std::ofstream omat1( testName+".csv" ); + + + std::vector< std::vector< double > > fmat1( matrix1.numRows(), std::vector< double >( matrix1.numRows(), 0.0 )); + std::vector< std::vector< double > > fmat2( matrix2.numRows(), std::vector< double >( matrix2.numRows(), 0.0 )); + + for( localIndex i = 0; i < matrix1.numRows(); ++i ) + { + arraySlice1d< globalIndex const > indices1 = matrix1.getColumns( i ); + arraySlice1d< globalIndex const > indices2 = matrix2.getColumns( i ); + arraySlice1d< double const > values1 = matrix1.getEntries( i ); + arraySlice1d< double const > values2 = matrix2.getEntries( i ); + for( integer j=0; j const & rsd1, + array1d< real64 > const & rsd2, std::string const & testName ) +{ + std::ofstream omat1( testName+".csv" ); + + for( integer i=0; i +void testWellEstimatorNumericalJacobian( CompositionalMultiphaseReservoirAndWells< CompositionalMultiphaseBase > & solver, + DomainPartition & domain, + real64 const perturbParameter, + real64 const time_n, + real64 const relTol, std::string const & testName, + LAMBDA && assembleFunction ) +{ + CompositionalMultiphaseWell & wellSolver = *solver.wellSolver(); + CompositionalMultiphaseFVM & flowSolver = dynamicCast< CompositionalMultiphaseFVM & >( *solver.reservoirSolver() ); + + localIndex const NC = flowSolver.numFluidComponents(); + + CRSMatrix< real64, globalIndex > const & jacobian = wellSolver.getLocalMatrix(); + array1d< real64 > residual( jacobian.numRows() ); + DofManager const & dofManager = wellSolver.getDofManager(); + + // assemble the analytical residual + solver.resetStateToBeginningOfStep( domain ); + + residual.zero(); + jacobian.zero(); + + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + WellControls & wellControls = wellSolver.getWellControls( subRegion ); + wellControls.setWellState( 1 ); + wellSolver.initializeWell( domain, mesh, subRegion, time_n ); + } ); + } ); + + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + residual.move( hostMemorySpace, false ); + + // copy the analytical residual + array1d< real64 > residualOrig( residual ); + + // create the numerical jacobian + jacobian.move( hostMemorySpace ); + CRSMatrix< real64, globalIndex > jacobianFD( jacobian ); + jacobianFD.zero(); + + + string const wellDofKey = dofManager.getKey( wellSolver.wellElementDofName() ); + + // at this point we start assembling the finite-difference block by block + + + ///////////////////////////////////////////////// + // Step 2) Compute the terms in J_RW and J_WW // + ///////////////////////////////////////////////// + + // loop over the wells + if( 1 ) + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + // get the degrees of freedom, ghosting info and next well elem index + arrayView1d< globalIndex const > const & wellElemDofNumber = + subRegion.getReference< array1d< globalIndex > >( wellDofKey ); + + // get the primary variables on the well elements + arrayView1d< real64 > const & wellElemPressure = + subRegion.getField< fields::well::pressure >(); + wellElemPressure.move( hostMemorySpace, false ); + + arrayView1d< real64 > const & wellElemTemperature = + subRegion.getField< fields::well::temperature >(); + wellElemTemperature.move( hostMemorySpace, false ); + + arrayView2d< real64, compflow::USD_COMP > const & wellElemCompDens = + subRegion.getField< fields::well::globalCompDensity >(); + wellElemCompDens.move( hostMemorySpace, false ); + + arrayView1d< real64 > const & connRate = + subRegion.getField< fields::well::mixtureConnectionRate >(); + connRate.move( hostMemorySpace, false ); + + // a) compute all the derivatives wrt to the pressure in WELL elem iwelem + for( localIndex iwelem = 0; iwelem < subRegion.size(); ++iwelem ) + { + + real64 wellElemTotalDensity = 0.0; + for( localIndex ic = 0; ic < NC; ++ic ) + { + wellElemTotalDensity += wellElemCompDens[iwelem][ic]; + } + + { + solver.resetStateToBeginningOfStep( domain ); + + // here is the perturbation in the pressure of the well element + 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 ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + wellElemDofNumber[iwelem] + compositionalMultiphaseWellKernels::ColOffset::DPRES, + dP, + jacobianFD.toViewConstSizes() ); + } + + for( localIndex jc = 0; jc < NC; ++jc ) + { + solver.resetStateToBeginningOfStep( domain ); + + real64 const dRho = perturbParameter * wellElemTotalDensity; + wellElemCompDens.move( hostMemorySpace, true ); + wellElemCompDens[iwelem][jc] += dRho; + + wellSolver.updateState( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + wellElemDofNumber[iwelem] + compositionalMultiphaseWellKernels::ColOffset::DCOMP + jc, + dRho, + jacobianFD.toViewConstSizes() ); + } + { + solver.resetStateToBeginningOfStep( domain ); + residual.zero(); + jacobian.zero(); + // here is the perturbation in the temperature of the well element + real64 const dT = perturbParameter * ( wellElemTemperature[iwelem] + perturbParameter ); + wellElemTemperature.move( hostMemorySpace, true ); + wellElemTemperature[iwelem] += dT; + + // after perturbing, update the pressure-dependent quantities in the well + wellSolver.updateState( domain ); + + + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + wellElemDofNumber[iwelem] + compositionalMultiphaseWellKernels::ColOffset::DCOMP + NC+1, + dT, + jacobianFD.toViewConstSizes() ); + + } + } + + + // b) compute all the derivatives wrt to the connection in WELL elem + // iwelem + for( localIndex iwelem = 0; iwelem < subRegion.size(); ++iwelem ) + { + { + solver.resetStateToBeginningOfStep( domain ); + + // here is the perturbation in the rate of the well element + real64 const dRate = perturbParameter * ( connRate[iwelem] + perturbParameter ); + connRate.move( hostMemorySpace, true ); + connRate[iwelem] += dRate; + + wellSolver.updateState( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + wellElemDofNumber[iwelem] + compositionalMultiphaseWellKernels::ColOffset::DCOMP + NC, + dRate, + jacobianFD.toViewConstSizes() ); + } + } + } ); + } ); + + // assemble the analytical jacobian + solver.resetStateToBeginningOfStep( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + printCompareLocalMatrices( jacobian.toViewConst(), jacobianFD.toViewConst(), testName ); + compareLocalMatrices( jacobian.toViewConst(), jacobianFD.toViewConst(), relTol ); +} +template< typename LAMBDA > +void testNumericalJacobian( CompositionalMultiphaseReservoirAndWells< CompositionalMultiphaseBase > & solver, + DomainPartition & domain, + real64 const perturbParameter, + real64 const relTol, std::string const & testName, + LAMBDA && assembleFunction ) +{ + CompositionalMultiphaseWell & wellSolver = *solver.wellSolver(); + CompositionalMultiphaseFVM & flowSolver = dynamicCast< CompositionalMultiphaseFVM & >( *solver.reservoirSolver() ); + + localIndex const NC = flowSolver.numFluidComponents(); + + CRSMatrix< real64, globalIndex > const & jacobian = solver.getLocalMatrix(); + array1d< real64 > residual( jacobian.numRows() ); + DofManager const & dofManager = solver.getDofManager(); + + // assemble the analytical residual + solver.resetStateToBeginningOfStep( domain ); + + residual.zero(); + jacobian.zero(); + + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + residual.move( hostMemorySpace, false ); + + // copy the analytical residual + array1d< real64 > residualOrig( residual ); + + // create the numerical jacobian + jacobian.move( hostMemorySpace ); + CRSMatrix< real64, globalIndex > jacobianFD( jacobian ); + jacobianFD.zero(); + + string const resDofKey = dofManager.getKey( wellSolver.resElementDofName() ); + string const wellDofKey = dofManager.getKey( wellSolver.wellElementDofName() ); + + // at this point we start assembling the finite-difference block by block + + //////////////////////////////////////////////// + // Step 1) Compute the terms in J_RR and J_WR // + //////////////////////////////////////////////// + if( 1 ) + domain.forMeshBodies( [&] ( MeshBody & meshBody ) + { + meshBody.forMeshLevels( [&] ( MeshLevel & mesh ) + { + ElementRegionManager & elemManager = mesh.getElemManager(); + for( localIndex er = 0; er < elemManager.numRegions(); ++er ) + { + ElementRegionBase & elemRegion = elemManager.getRegion( er ); + elemRegion.forElementSubRegionsIndex< CellElementSubRegion >( [&]( localIndex const, CellElementSubRegion & subRegion ) + { + // get the degrees of freedom and ghosting information + arrayView1d< globalIndex const > const & dofNumber = + subRegion.getReference< array1d< globalIndex > >( resDofKey ); + + // get the primary variables on the reservoir elements + arrayView1d< real64 > const & pres = + subRegion.getField< fields::flow::pressure >(); + pres.move( hostMemorySpace, false ); + + arrayView2d< real64, compflow::USD_COMP > const & compDens = + subRegion.getField< fields::flow::globalCompDensity >(); + compDens.move( hostMemorySpace, false ); + + arrayView1d< real64 > const & temp = + subRegion.getField< fields::flow::temperature >(); + temp.move( hostMemorySpace, false ); + + // a) compute all the derivatives wrt to the pressure in RESERVOIR elem ei + for( localIndex ei = 0; ei < subRegion.size(); ++ei ) + { + real64 totalDensity = 0.0; + for( localIndex ic = 0; ic < NC; ++ic ) + { + totalDensity += compDens[ei][ic]; + } + + { + solver.resetStateToBeginningOfStep( domain ); + + // here is the perturbation in the pressure of the element + real64 const dP = perturbParameter * (pres[ei] + perturbParameter); + pres.move( hostMemorySpace, true ); + pres[ei] += dP; + + // after perturbing, update the pressure-dependent quantities in the reservoir + flowSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh2, + string_array const & regionNames2 ) + { + mesh2.getElemManager().forElementSubRegions( regionNames2, + [&]( localIndex const, + ElementSubRegionBase & subRegion2 ) + { + flowSolver.updateFluidState( subRegion2 ); + } ); + } ); + + wellSolver.updateState( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + dofNumber[ei], + dP, + jacobianFD.toViewConstSizes() ); + } + + for( localIndex jc = 0; jc < NC; ++jc ) + { + solver.resetStateToBeginningOfStep( domain ); + + real64 const dRho = perturbParameter * totalDensity; + compDens.move( hostMemorySpace, true ); + compDens[ei][jc] += dRho; + + flowSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh2, + string_array const & regionNames2 ) + { + mesh2.getElemManager().forElementSubRegions( regionNames2, + [&]( localIndex const, + ElementSubRegionBase & subRegion2 ) + { + flowSolver.updateFluidState( subRegion2 ); + } ); + } ); + wellSolver.updateState( domain ); + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + dofNumber[ei] + jc + 1, + dRho, + jacobianFD.toViewConstSizes() ); + } + { + solver.resetStateToBeginningOfStep( domain ); + + // here is the perturbation in the pressure of the element + real64 const dTemp = perturbParameter * (temp[ei] + perturbParameter); + temp.move( hostMemorySpace, true ); + temp[ei] += dTemp; + + // after perturbing, update the pressure-dependent quantities in the reservoir + flowSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh2, + string_array const & regionNames2 ) + { + mesh2.getElemManager().forElementSubRegions( regionNames2, + [&]( localIndex const, + ElementSubRegionBase & subRegion2 ) + { + flowSolver.updateFluidState( subRegion2 ); + } ); + } ); + + wellSolver.updateState( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + dofNumber[ei]+NC+1, + dTemp, + jacobianFD.toViewConstSizes() ); + } + } + } ); + } + } ); + + } ); + + ///////////////////////////////////////////////// + // Step 2) Compute the terms in J_RW and J_WW // + ///////////////////////////////////////////////// + + // loop over the wells + if( 1 ) + wellSolver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + // get the degrees of freedom, ghosting info and next well elem index + arrayView1d< globalIndex const > const & wellElemDofNumber = + subRegion.getReference< array1d< globalIndex > >( wellDofKey ); + + // get the primary variables on the well elements + arrayView1d< real64 > const & wellElemPressure = + subRegion.getField< fields::well::pressure >(); + wellElemPressure.move( hostMemorySpace, false ); + + arrayView1d< real64 > const & wellElemTemperature = + subRegion.getField< fields::well::temperature >(); + wellElemTemperature.move( hostMemorySpace, false ); + + arrayView2d< real64, compflow::USD_COMP > const & wellElemCompDens = + subRegion.getField< fields::well::globalCompDensity >(); + wellElemCompDens.move( hostMemorySpace, false ); + + arrayView1d< real64 > const & connRate = + subRegion.getField< fields::well::mixtureConnectionRate >(); + connRate.move( hostMemorySpace, false ); + + // a) compute all the derivatives wrt to the pressure in WELL elem iwelem + for( localIndex iwelem = 0; iwelem < subRegion.size(); ++iwelem ) + { + + real64 wellElemTotalDensity = 0.0; + for( localIndex ic = 0; ic < NC; ++ic ) + { + wellElemTotalDensity += wellElemCompDens[iwelem][ic]; + } + + { + solver.resetStateToBeginningOfStep( domain ); + + // here is the perturbation in the pressure of the well element + 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 ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + wellElemDofNumber[iwelem] + compositionalMultiphaseWellKernels::ColOffset::DPRES, + dP, + jacobianFD.toViewConstSizes() ); + } + + for( localIndex jc = 0; jc < NC; ++jc ) + { + solver.resetStateToBeginningOfStep( domain ); + + real64 const dRho = perturbParameter * wellElemTotalDensity; + wellElemCompDens.move( hostMemorySpace, true ); + wellElemCompDens[iwelem][jc] += dRho; + + wellSolver.updateState( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + wellElemDofNumber[iwelem] + compositionalMultiphaseWellKernels::ColOffset::DCOMP + jc, + dRho, + jacobianFD.toViewConstSizes() ); + } + { + solver.resetStateToBeginningOfStep( domain ); + residual.zero(); + jacobian.zero(); + // here is the perturbation in the temperature of the well element + real64 const dT = perturbParameter * ( wellElemTemperature[iwelem] + perturbParameter ); + wellElemTemperature.move( hostMemorySpace, true ); + wellElemTemperature[iwelem] += dT; + + // after perturbing, update the pressure-dependent quantities in the well + wellSolver.updateState( domain ); + + + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + wellElemDofNumber[iwelem] + compositionalMultiphaseWellKernels::ColOffset::DCOMP + NC+1, + dT, + jacobianFD.toViewConstSizes() ); + + } + } + + + // b) compute all the derivatives wrt to the connection in WELL elem + // iwelem + for( localIndex iwelem = 0; iwelem < subRegion.size(); ++iwelem ) + { + { + solver.resetStateToBeginningOfStep( domain ); + + // here is the perturbation in the rate of the well element + real64 const dRate = perturbParameter * ( connRate[iwelem] + perturbParameter ); + connRate.move( hostMemorySpace, true ); + connRate[iwelem] += dRate; + + wellSolver.updateState( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + wellElemDofNumber[iwelem] + compositionalMultiphaseWellKernels::ColOffset::DCOMP + NC, + dRate, + jacobianFD.toViewConstSizes() ); + } + } + } ); + } ); + + // assemble the analytical jacobian + solver.resetStateToBeginningOfStep( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView() ); + printCompareLocalMatrices( jacobian.toViewConst(), jacobianFD.toViewConst(), testName ); + compareLocalMatrices( jacobian.toViewConst(), jacobianFD.toViewConst(), relTol ); +} + +class CompositionalMultiphaseReservoirSolverTest : public ::testing::Test +{ +public: + + CompositionalMultiphaseReservoirSolverTest(): + state( std::make_unique< CommandLineOptions >( g_commandLineOptions ) ) + {} + +protected: + + void SetUp() override + { + setupProblemFromXML( state.getProblemManager(), xmlInput ); + solver = &state.getProblemManager().getPhysicsSolverManager().getGroup< CompositionalMultiphaseReservoirAndWells< CompositionalMultiphaseBase > >( "reservoirSystem" ); + + DomainPartition & domain = state.getProblemManager().getDomainPartition(); + + solver->setupSystem( domain, + solver->getDofManager(), + solver->getLocalMatrix(), + solver->getSystemRhs(), + solver->getSystemSolution() ); + + solver->wellSolver()->setupSystem( domain, + solver->wellSolver()->getDofManager(), + solver->wellSolver()->getLocalMatrix(), + solver->wellSolver()->getSystemRhs(), + solver->wellSolver()->getSystemSolution() ); + + solver->implicitStepSetup( time, dt, domain ); + + } + + static real64 constexpr time = 0.0; + static real64 constexpr dt = 1e4; + static real64 constexpr eps = std::numeric_limits< real64 >::epsilon(); + + GeosxState state; + CompositionalMultiphaseReservoirAndWells< CompositionalMultiphaseBase > * solver; +}; + +real64 constexpr CompositionalMultiphaseReservoirSolverTest::time; +real64 constexpr CompositionalMultiphaseReservoirSolverTest::dt; +real64 constexpr CompositionalMultiphaseReservoirSolverTest::eps; + + +TEST_F( CompositionalMultiphaseReservoirSolverTest, jacobianNumericalCheck_Perforation ) +{ + real64 const perturb = std::sqrt( eps ); + real64 const tol = 1e-1; // 10% error margin + + DomainPartition & domain = state.getProblemManager().getDomainPartition(); + + testWellEstimatorNumericalJacobian( *solver, domain, perturb, time, tol, "WellEstimator", + [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) + { + + DofManager const & dofManager = solver->wellSolver()->getDofManager(); + solver->wellSolver()->forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + ElementRegionManager & elemManager = mesh.getElemManager(); + elemManager.forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + // call assemble to fill the matrix and the rhs + solver->wellSolver()->assembleWellSystem( time, + dt, + elemManager, + subRegion, + dofManager, + localMatrix, + localRhs ); + +// apply boundary conditions to system + + solver->wellSolver()->applyWellBoundaryConditions( time, + dt, + elemManager, + subRegion, + dofManager, + localRhs, + localMatrix ); + } ); + } ); + + + + } ); +} + + +int main( int argc, char * * argv ) +{ + writeTableToFile( "co2flash.txt", co2flash ); + writeTableToFile( "pvtliquid.txt", pvtLiquid ); + writeTableToFile( "pvtgas.txt", pvtGas ); + ::testing::InitGoogleTest( &argc, argv ); + g_commandLineOptions = *geos::basicSetup( argc, argv ); + int const result = RUN_ALL_TESTS(); + geos::basicCleanup(); + removeFile( "co2flash.txt" ); + removeFile( "pvtliquid.txt" ); + removeFile( "pvtgas.txt" ); + + return result; +} diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index fde973cfb61..ed9269bc5a7 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -60,7 +60,15 @@ // tjb wrong place #include "physicsSolvers/multiphysics/CoupledReservoirAndWellKernels.hpp" - +#include "common/MpiWrapper.hpp" +#include "physicsSolvers/fluidFlow/StencilAccessors.hpp" +#include "physicsSolvers/fluidFlow/wells/WellControls.hpp" +#include "mainInterface/ProblemManager.hpp" +#include "events/EventManager.hpp" +#include "physicsSolvers/PhysicsSolverManager.hpp" +#include "physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.hpp" +#include "physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.hpp" +#include "physicsSolvers/fluidFlow/wells/LogLevelsInfo.hpp" #if defined( __INTEL_COMPILER ) #pragma GCC optimize "O0" #endif @@ -83,7 +91,8 @@ CompositionalMultiphaseWell::CompositionalMultiphaseWell( const string & name, m_maxAbsolutePresChange( -1 ), // disabled by default m_minScalingFactor( 0.01 ), m_allowCompDensChopping( 1 ), - m_targetPhaseIndex( -1 ) + m_targetPhaseIndex( -1 ), + m_wellDebugInit( false ) { this->registerWrapper( viewKeyStruct::useMassFlagString(), &m_useMass ). setApplyDefaultValue( 0 ). @@ -465,6 +474,486 @@ void CompositionalMultiphaseWell::initializePostSubGroups() } +void CompositionalMultiphaseWell::outputWellDebug( real64 const time, + real64 const dt, + integer num_timesteps, + integer num_timestep_cuts, + integer current_newton_iteration, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + // tjbreturn; + GEOS_UNUSED_VAR( time ); + GEOS_UNUSED_VAR( dofManager ); + GEOS_UNUSED_VAR( localMatrix ); + GEOS_UNUSED_VAR( localRhs ); + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + + if( m_writeSegDebug > 0 ) + { + CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); + auto solver_names = getParent().getSubGroupsNames(); + //integer n = solver_names.size(); + // Bit of a hack, cases with > 3 solvers we need to find the base solver for wells + // Assume that solver definition order follows coupledreswell, res, and then well + //std::string coupled_solver_name = solver_names[n-3]; + + //GeosxState & gs = getGlobalState(); + + //CompositionalMultiphaseReservoirAndWells< CompositionalMultiphaseBase > * solver = + // &(gs.getProblemManager().getPhysicsSolverManager().getGroup< geos::CompositionalMultiphaseReservoirAndWells< + // geos::CompositionalMultiphaseBase > >( coupled_solver_name )); + + EventManager const & event = getGroupByPath< EventManager >( "/Problem/Events" ); + real64 const & ctime = event.getReference< real64 >( EventManager::viewKeyStruct::timeString() ); + //real64 const dt = event.getReference< real64 >( EventManager::viewKeyStruct::dtString() ); + integer const & cycle = event.getReference< integer >( EventManager::viewKeyStruct::cycleString() ); + integer const & subevent = event.getReference< integer >( EventManager::viewKeyStruct::currentSubEventString() ); + + + // std::cout << "tjbtime1 " << ctime << " " << m_globalNumTimeSteps << " " << dt << " " << cycle << " " << subevent + // << " " << m_numTimeStepCuts << " " << m_currentNewtonIteration << std::endl; + if( true ) // need to fix for restarts cycle >= m_writeSegDebug ) + { + //SolverStatistics & solver_stat = solver->getSolverStatistics(); + //integer num_timesteps = solver_stat.getReference< integer >( SolverStatistics::viewKeyStruct::numTimeStepsString()); + //integer current_newton_iteration = solver_stat.getReference< integer >( + // SolverStatistics::viewKeyStruct::numCurrentNonlinearIterationsString()); + //integer num_timestep_cuts = solver_stat.getReference< integer >( SolverStatistics::viewKeyStruct::numTimeStepCutsString()); + //std::cout << "tjbtime2 " << ctime << " " << m_globalNumTimeSteps << " " << dt << " " << cycle << " " << subevent + //<< " " << m_numTimeStepCuts << " " << m_currentNewtonIteration << std::endl; + string & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + fluidName = getConstitutiveName< MultiFluidBase >( subRegion ); + WellControls & wellControls = getWellControls( subRegion ); + + + MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); + PerforationData & perforationData = *subRegion.getPerforationData(); + using CompFlowAccessors = + StencilAccessors< fields::flow::pressure, + fields::flow::temperature, + fields::flow::phaseVolumeFraction, + + + + fields::flow::dPhaseVolumeFraction, + fields::flow::globalCompDensity, + fields::flow::dGlobalCompFraction_dGlobalCompDensity >; + string const flowSolverName = flowSolver.getName(); + CompFlowAccessors compFlowAccessors( mesh.getElemManager(), flowSolver.getName() ); + + using MultiFluidAccessors = + StencilMaterialAccessors< MultiFluidBase, + fields::multifluid::phaseEnthalpy, + fields::multifluid::phaseDensity, + fields::multifluid::phaseViscosity, + fields::multifluid::dPhaseDensity, + fields::multifluid::phaseViscosity, + fields::multifluid::phaseInternalEnergy, + fields::multifluid::dPhaseViscosity, + fields::multifluid::phaseCompFraction, + fields::multifluid::dPhaseCompFraction >; + MultiFluidAccessors multiFluidAccessors( mesh.getElemManager(), flowSolver.getName() ); + + using RelPermAccessors = + StencilMaterialAccessors< RelativePermeabilityBase, + fields::relperm::phaseRelPerm, + fields::relperm::dPhaseRelPerm_dPhaseVolFraction >; + + RelPermAccessors relPermAccessors( mesh.getElemManager(), flowSolver.getName() ); + + + string const srn = subRegion.getName(); + + std::vector< string > cp_der {"dP", "dT"}; + for( integer i=0; i()); + if( isThermal() ) + { + m_wellPropWriter[srn].registerSegProp( "Temperature", subRegion.getField< fields::well::temperature >()); + } + m_wellPropWriter[srn].registerSegComponentProp( "ComponentDensity", subRegion.getField< fields::well::globalCompDensity >()); + + m_wellPropWriter[srn].registerSegProp( "TotalRate", subRegion.getField< fields::well::mixtureConnectionRate >()); + + m_wellPropWriter[srn].registerSegProp( "MassDensity", subRegion.getField< fields::well::totalMassDensity >()); + + m_wellPropWriter[srn].registerSegComponentProp( "CompFraction", subRegion.getField< fields::well::globalCompFraction >()); + + m_wellPropWriter[srn].registerSegPhasePropf( "PhaseDensity", fluid.phaseMassDensity()); + m_wellPropWriter[srn].registerSegPhasePropf( "PhaseViscosity", fluid.phaseViscosity()); + m_wellPropWriter[srn].registerSegPhasePropDerf( "dPhaseDensity", cp_der, fluid.dPhaseMassDensity()); + m_wellPropWriter[srn].registerSegPhaseProp( "PhaseVolumeFraction", subRegion.getField< fields::well::phaseVolumeFraction >()); + m_wellPropWriter[srn].registerSegPhasePropDer( "dPhaseVolume", cp_der, subRegion.getField< fields::well::dPhaseVolumeFraction >()); + if( isThermal() ) + { + m_wellPropWriter[srn].registerSegPhasePropf( "InternalEnergy", fluid.phaseInternalEnergy()); + m_wellPropWriter[srn].registerSegPhasePropDerf( "dPhaseEnthalpy", cp_der, fluid.dPhaseEnthalpy()); + + m_wellPropWriter[srn].registerSegPhasePropf( "PhaseEnthalpy", fluid.phaseEnthalpy()); + m_wellPropWriter[srn].registerSegPhasePropDerf( "dPhaseInternalEnergy", cp_der, fluid.dPhaseInternalEnergy()); + } + m_wellPropWriter[srn].registerSegPhaseComponentPropf( "PhaseCompFrac", fluid.phaseCompFraction()); + + // Perforation properties + m_wellPropWriter[srn].registerPerf2dProp( {"X", "Y", "Z"}, perforationData.getLocation()); + m_wellPropWriter[srn].registerPerfResProp( "Pressure", compFlowAccessors.get( fields::flow::pressure {} )); + if( isThermal() ) + { + m_wellPropWriter[srn].registerPerfResProp( "Temperature", compFlowAccessors.get( fields::flow::temperature{} )); + m_wellPropWriter[srn].registerPerfResPhasePropf( "Enthalpy", multiFluidAccessors.get( fields::multifluid::phaseEnthalpy{} )); + m_wellPropWriter[srn].registerPerfResPhasePropf( "InternalEnergy", multiFluidAccessors.get( fields::multifluid::phaseInternalEnergy{} )); + } + m_wellPropWriter[srn].registerPerfComponentProp( "CompPerfRate", perforationData.getField< fields::well::compPerforationRate >()); + m_wellPropWriter[srn].registerPerfResComponentProp( "ComponentDensity", compFlowAccessors.get( fields::flow::globalCompDensity{} )); + m_wellPropWriter[srn].registerPerfResPhaseComponentProp( "PhaseCompFrac", multiFluidAccessors.get( fields::multifluid::phaseCompFraction{} )); + m_wellPropWriter[srn].registerPerfResPhaseProp( "PhaseVolFrac", compFlowAccessors.get( fields::flow::phaseVolumeFraction{} )); + m_wellPropWriter[srn].registerPerfResPhasePropf( "Viscosity", multiFluidAccessors.get( fields::multifluid::phaseViscosity{} )); + m_wellPropWriter[srn].registerPerfResPhasePropf( "RelPerm", relPermAccessors.get( fields::relperm::phaseRelPerm{} )); + + m_wellPropWriter[srn].write( ctime, dt, cycle, subevent, num_timesteps, + current_newton_iteration, + num_timestep_cuts ); + } + } + } ); + } ); + +} + +void CompositionalMultiphaseWell::outputSingleWellDebug( real64 const time, + real64 const dt, + integer num_timesteps, + integer current_newton_iteration, + integer num_timestep_cuts, + MeshLevel & mesh, + WellElementSubRegion & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< const real64 > const & localRhs ) +{ + GEOS_UNUSED_VAR( time ); + GEOS_UNUSED_VAR( dofManager ); + GEOS_UNUSED_VAR( localMatrix ); + GEOS_UNUSED_VAR( localRhs ); + + + if( m_writeSegDebug > 0 ) + { + CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); + auto solver_names = getParent().getSubGroupsNames(); +//integer n = solver_names.size(); +// Bit of a hack, cases with > 3 solvers we need to find the base solver for wells +// Assume that solver definition order follows coupledreswell, res, and then well +//std::string coupled_solver_name = solver_names[n-3]; + +//GeosxState & gs = getGlobalState(); + +//CompositionalMultiphaseReservoirAndWells< CompositionalMultiphaseBase > * solver = +// &(gs.getProblemManager().getPhysicsSolverManager().getGroup< geos::CompositionalMultiphaseReservoirAndWells< +// geos::CompositionalMultiphaseBase > >( coupled_solver_name )); + + EventManager const & event = getGroupByPath< EventManager >( "/Problem/Events" ); + // real64 const & ctime = event.getReference< real64 >( EventManager::viewKeyStruct::timeString() ); +//real64 const dt = event.getReference< real64 >( EventManager::viewKeyStruct::dtString() ); + integer const & cycle = event.getReference< integer >( EventManager::viewKeyStruct::cycleString() ); + integer const & subevent = event.getReference< integer >( EventManager::viewKeyStruct::currentSubEventString() ); + + +// std::cout << "tjbtime1 " << ctime << " " << m_globalNumTimeSteps << " " << dt << " " << cycle << " " << subevent +// << " " << m_numTimeStepCuts << " " << m_currentNewtonIteration << std::endl; + if( true ) // need to fix for restarts cycle >= m_writeSegDebug ) + { +//SolverStatistics & solver_stat = solver->getSolverStatistics(); +//integer num_timesteps = solver_stat.getReference< integer >( SolverStatistics::viewKeyStruct::numTimeStepsString()); +//integer current_newton_iteration = solver_stat.getReference< integer >( +// SolverStatistics::viewKeyStruct::numCurrentNonlinearIterationsString()); +//integer num_timestep_cuts = solver_stat.getReference< integer >( SolverStatistics::viewKeyStruct::numTimeStepCutsString()); +//std::cout << "tjbtime2 " << ctime << " " << m_globalNumTimeSteps << " " << dt << " " << cycle << " " << subevent +//<< " " << m_numTimeStepCuts << " " << m_currentNewtonIteration << std::endl; + string & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + fluidName = getConstitutiveName< MultiFluidBase >( subRegion ); + WellControls & wellControls = getWellControls( subRegion ); + + + MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); + PerforationData & perforationData = *subRegion.getPerforationData(); + using CompFlowAccessors = + StencilAccessors< fields::flow::pressure, + fields::flow::temperature, + fields::flow::phaseVolumeFraction, + + + + fields::flow::dPhaseVolumeFraction, + fields::flow::globalCompDensity, + fields::flow::dGlobalCompFraction_dGlobalCompDensity >; + string const flowSolverName = flowSolver.getName(); + CompFlowAccessors compFlowAccessors( mesh.getElemManager(), flowSolver.getName() ); + + using MultiFluidAccessors = + StencilMaterialAccessors< MultiFluidBase, + fields::multifluid::phaseEnthalpy, + fields::multifluid::phaseDensity, + fields::multifluid::phaseViscosity, + fields::multifluid::dPhaseDensity, + fields::multifluid::phaseViscosity, + fields::multifluid::phaseInternalEnergy, + fields::multifluid::dPhaseViscosity, + fields::multifluid::phaseCompFraction, + fields::multifluid::dPhaseCompFraction >; + MultiFluidAccessors multiFluidAccessors( mesh.getElemManager(), flowSolver.getName() ); + + using RelPermAccessors = + StencilMaterialAccessors< RelativePermeabilityBase, + fields::relperm::phaseRelPerm, + fields::relperm::dPhaseRelPerm_dPhaseVolFraction >; + + RelPermAccessors relPermAccessors( mesh.getElemManager(), flowSolver.getName() ); + + + string const srn = subRegion.getName(); + + std::vector< string > cp_der {"dP", "dT"}; + for( integer i=0; i()); + if( isThermal() ) + { + m_wellPropWriter[srn].registerSegProp( "Temperature", subRegion.getField< fields::well::temperature >()); + } + m_wellPropWriter[srn].registerSegComponentProp( "ComponentDensity", subRegion.getField< fields::well::globalCompDensity >()); + + m_wellPropWriter[srn].registerSegProp( "TotalRate", subRegion.getField< fields::well::mixtureConnectionRate >()); + + m_wellPropWriter[srn].registerSegProp( "MassDensity", subRegion.getField< fields::well::totalMassDensity >()); + + m_wellPropWriter[srn].registerSegComponentProp( "CompFraction", subRegion.getField< fields::well::globalCompFraction >()); + + m_wellPropWriter[srn].registerSegPhasePropf( "PhaseDensity", fluid.phaseMassDensity()); + m_wellPropWriter[srn].registerSegPhasePropf( "PhaseViscosity", fluid.phaseViscosity()); + m_wellPropWriter[srn].registerSegPhasePropDerf( "dPhaseDensity", cp_der, fluid.dPhaseMassDensity()); + m_wellPropWriter[srn].registerSegPhaseProp( "PhaseVolumeFraction", subRegion.getField< fields::well::phaseVolumeFraction >()); + m_wellPropWriter[srn].registerSegPhasePropDer( "dPhaseVolume", cp_der, subRegion.getField< fields::well::dPhaseVolumeFraction >()); + if( isThermal() ) + { + m_wellPropWriter[srn].registerSegPhasePropf( "InternalEnergy", fluid.phaseInternalEnergy()); + m_wellPropWriter[srn].registerSegPhasePropDerf( "dPhaseEnthalpy", cp_der, fluid.dPhaseEnthalpy()); + + m_wellPropWriter[srn].registerSegPhasePropf( "PhaseEnthalpy", fluid.phaseEnthalpy()); + m_wellPropWriter[srn].registerSegPhasePropDerf( "dPhaseInternalEnergy", cp_der, fluid.dPhaseInternalEnergy()); + } + m_wellPropWriter[srn].registerSegPhaseComponentPropf( "PhaseCompFrac", fluid.phaseCompFraction()); + +// Perforation properties + m_wellPropWriter[srn].registerPerf2dProp( {"X", "Y", "Z"}, perforationData.getLocation()); + m_wellPropWriter[srn].registerPerfResProp( "Pressure", compFlowAccessors.get( fields::flow::pressure {} )); + if( isThermal() ) + { + m_wellPropWriter[srn].registerPerfResProp( "Temperature", compFlowAccessors.get( fields::flow::temperature{} )); + m_wellPropWriter[srn].registerPerfResPhasePropf( "Enthalpy", multiFluidAccessors.get( fields::multifluid::phaseEnthalpy{} )); + m_wellPropWriter[srn].registerPerfResPhasePropf( "InternalEnergy", multiFluidAccessors.get( fields::multifluid::phaseInternalEnergy{} )); + } + m_wellPropWriter[srn].registerPerfComponentProp( "CompPerfRate", perforationData.getField< fields::well::compPerforationRate >()); + m_wellPropWriter[srn].registerPerfResComponentProp( "ComponentDensity", compFlowAccessors.get( fields::flow::globalCompDensity{} )); + m_wellPropWriter[srn].registerPerfResPhaseComponentProp( "PhaseCompFrac", multiFluidAccessors.get( fields::multifluid::phaseCompFraction{} )); + m_wellPropWriter[srn].registerPerfResPhaseProp( "PhaseVolFrac", compFlowAccessors.get( fields::flow::phaseVolumeFraction{} )); + m_wellPropWriter[srn].registerPerfResPhasePropf( "Viscosity", multiFluidAccessors.get( fields::multifluid::phaseViscosity{} )); + m_wellPropWriter[srn].registerPerfResPhasePropf( "RelPerm", relPermAccessors.get( fields::relperm::phaseRelPerm{} )); + + m_wellPropWriter[srn].write( my_ctime, dt, cycle, subevent, num_timesteps, + current_newton_iteration, + num_timestep_cuts ); + } + + } + + +} + + +void CompositionalMultiphaseWell::printSegRates( real64 const & time, + real64 const & dt, + integer num_timesteps, + integer num_timestep_cuts, + integer current_newton_iteration, + DomainPartition & domain ) +{ + GEOS_UNUSED_VAR( time ); + + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< WellElementSubRegion >( regionNames, + [&]( localIndex const, + WellElementSubRegion & subRegion ) + { + + if( m_writeSegDebug > 0 ) + { + CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); + auto solver_names = getParent().getSubGroupsNames(); + //integer n = solver_names.size(); + // Bit of a hack, cases with > 3 solvers we need to find the base solver for wells + // Assume that solver definition order follows coupledreswell, res, and then well + //std::string coupled_solver_name = solver_names[n-3]; + + //GeosxState & gs = getGlobalState(); + + //CompositionalMultiphaseReservoirAndWells< CompositionalMultiphaseBase > * solver = + // &(gs.getProblemManager().getPhysicsSolverManager().getGroup< geos::CompositionalMultiphaseReservoirAndWells< + // geos::CompositionalMultiphaseBase > >( coupled_solver_name )); + + EventManager const & event = getGroupByPath< EventManager >( "/Problem/Events" ); + real64 const & ctime = event.getReference< real64 >( EventManager::viewKeyStruct::timeString() ); + //real64 const & dt = event.getReference< real64 >( EventManager::viewKeyStruct::dtString() ); + integer const & cycle = event.getReference< integer >( EventManager::viewKeyStruct::cycleString() ); + integer const & subevent = event.getReference< integer >( EventManager::viewKeyStruct::currentSubEventString() ); + + + // std::cout << "tjbtime1 " << ctime << " " << m_globalNumTimeSteps << " " << dt << " " << cycle << " " << subevent + // << " " << m_numTimeStepCuts << " " << m_currentNewtonIteration << std::endl; + if( true ) // need to fix for restarts cycle >= m_writeSegDebug ) + { + //SolverStatistics & solver_stat = solver->getSolverStatistics(); + //integer num_timesteps = solver_stat.getReference< integer >( SolverStatistics::viewKeyStruct::numTimeStepsString()); + //integer current_newton_iteration = solver_stat.getReference< integer >( + // SolverStatistics::viewKeyStruct::numCurrentNonlinearIterationsString()); + //integer num_timestep_cuts = solver_stat.getReference< integer >( SolverStatistics::viewKeyStruct::numTimeStepCutsString()); + //std::cout << "tjbtime2 " << ctime << " " << m_globalNumTimeSteps << " " << dt << " " << cycle << " " << subevent + //<< " " << m_numTimeStepCuts << " " << m_currentNewtonIteration << std::endl; + string & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + fluidName = getConstitutiveName< MultiFluidBase >( subRegion ); + WellControls & wellControls = getWellControls( subRegion ); + + + MultiFluidBase const & fluid = subRegion.getConstitutiveModel< MultiFluidBase >( fluidName ); + PerforationData & perforationData = *subRegion.getPerforationData(); + using CompFlowAccessors = + StencilAccessors< fields::flow::pressure, + fields::flow::temperature, + fields::flow::phaseVolumeFraction, + fields::flow::dPhaseVolumeFraction, + fields::flow::globalCompDensity, + fields::flow::dGlobalCompFraction_dGlobalCompDensity >; + string const flowSolverName = flowSolver.getName(); + CompFlowAccessors compFlowAccessors( mesh.getElemManager(), flowSolver.getName() ); + + using MultiFluidAccessors = + StencilMaterialAccessors< MultiFluidBase, + fields::multifluid::phaseDensity, + fields::multifluid::dPhaseDensity, + fields::multifluid::phaseInternalEnergy, + fields::multifluid::phaseEnthalpy, + fields::multifluid::dPhaseDensity, + fields::multifluid::phaseViscosity, + fields::multifluid::dPhaseViscosity, + fields::multifluid::phaseCompFraction, + fields::multifluid::dPhaseCompFraction >; + MultiFluidAccessors multiFluidAccessors( mesh.getElemManager(), flowSolver.getName() ); + + using RelPermAccessors = + StencilMaterialAccessors< RelativePermeabilityBase, + fields::relperm::phaseRelPerm, + fields::relperm::dPhaseRelPerm_dPhaseVolFraction >; + + RelPermAccessors relPermAccessors( mesh.getElemManager(), flowSolver.getName() ); + + + string const srn = subRegion.getName(); + + std::vector< string > cp_der {"dP", "dT"}; + for( integer i=0; i()); + if( isThermal() ) + { + m_wellPropWriter_eot[srn].registerSegProp( "Temperature", subRegion.getField< fields::well::temperature >()); + } + m_wellPropWriter_eot[srn].registerSegComponentProp( "ComponentDensity", subRegion.getField< fields::well::globalCompDensity >()); + + m_wellPropWriter_eot[srn].registerSegProp( "TotalRate", subRegion.getField< fields::well::mixtureConnectionRate >()); + + m_wellPropWriter_eot[srn].registerSegProp( "MassDensity", subRegion.getField< fields::well::totalMassDensity >()); + + m_wellPropWriter_eot[srn].registerSegComponentProp( "CompFraction", subRegion.getField< fields::well::globalCompFraction >()); + + m_wellPropWriter_eot[srn].registerSegPhasePropf( "PhaseDensity", fluid.phaseMassDensity()); + m_wellPropWriter_eot[srn].registerSegPhasePropf( "PhaseViscosity", fluid.phaseViscosity()); + m_wellPropWriter_eot[srn].registerSegPhaseProp( "PhaseVolumeFraction", subRegion.getField< fields::well::phaseVolumeFraction >()); + if( isThermal() ) + { + m_wellPropWriter_eot[srn].registerSegPhasePropf( "InternalEnergy", fluid.phaseInternalEnergy()); + m_wellPropWriter_eot[srn].registerSegPhasePropf( "PhaseEnthalpy", fluid.phaseEnthalpy()); + } + m_wellPropWriter_eot[srn].registerSegPhaseComponentPropf( "PhaseCompFrac", fluid.phaseCompFraction()); + + // Perforation properties + m_wellPropWriter_eot[srn].registerPerf2dProp( {"X", "Y", "Z"}, perforationData.getLocation()); + + + m_wellPropWriter_eot[srn].registerPerfResProp( "Pressure", compFlowAccessors.get( fields::flow::pressure {} )); + if( isThermal() ) + { + m_wellPropWriter_eot[srn].registerPerfResProp( "Temperature", compFlowAccessors.get( fields::flow::temperature{} )); + m_wellPropWriter[srn].registerPerfResPhaseProp( "Enthalpy", multiFluidAccessors.get( fields::multifluid::phaseEnthalpy{} )); + } + m_wellPropWriter_eot[srn].registerPerfComponentProp( "CompPerfRate", perforationData.getField< fields::well::compPerforationRate >()); + m_wellPropWriter_eot[srn].registerPerfResComponentProp( "ComponentDensity", compFlowAccessors.get( fields::flow::globalCompDensity{} )); + m_wellPropWriter_eot[srn].registerPerfResPhaseComponentProp( "PhaseCompFrac", multiFluidAccessors.get( fields::multifluid::phaseCompFraction{} )); + m_wellPropWriter_eot[srn].registerPerfResPhaseProp( "PhaseVolFrac", compFlowAccessors.get( fields::flow::phaseVolumeFraction{} )); + m_wellPropWriter_eot[srn].registerPerfResPhasePropf( "Viscosity", multiFluidAccessors.get( fields::multifluid::phaseViscosity{} )); + m_wellPropWriter_eot[srn].registerPerfResPhasePropf( "RelPerm", relPermAccessors.get( fields::relperm::phaseRelPerm{} )); + + m_wellPropWriter_eot[srn].write( ctime, dt, cycle, subevent, num_timesteps, + current_newton_iteration, + num_timestep_cuts ); + } + } + } ); + } ); + +} void CompositionalMultiphaseWell::initializePostInitialConditionsPreSubGroups() { WellSolverBase::initializePostInitialConditionsPreSubGroups(); @@ -1106,9 +1595,9 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh { if( wellControls.isProducer() ) { - wellControls.forSubGroups< MinimumBHPConstraint >( [&]( auto & constraint ) - //wellControls.forSubGroups< PhaseProductionConstraint >( [&]( auto & constraint - // ) + //wellControls.forSubGroups< MinimumBHPConstraint >( [&]( auto & constraint ) + wellControls.forSubGroups< ProductionConstraint< VolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, ProductionConstraint< PhaseVolumeRateConstraint > >( [&]( + auto & constraint ) { wellControls.setCurrentConstraint( &constraint ); wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old @@ -1118,7 +1607,7 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh { // tjb needed for backward compatibility //wellControls.forSubGroups< MaximumBHPConstraint >( [&]( auto & constraint ) - wellControls.forSubGroups< InjectionConstraint< VolumeRateConstraint > >( [&]( auto & constraint ) + wellControls.forSubGroups< InjectionConstraint< VolumeRateConstraint >, InjectionConstraint< MassRateConstraint >, InjectionConstraint< PhaseVolumeRateConstraint > >( [&]( auto & constraint ) { wellControls.setCurrentConstraint( &constraint ); wellControls.setControl( static_cast< WellControls::Control >(constraint.getControl()) ); // tjb old @@ -1142,7 +1631,7 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh arrayView1d< real64 const > const & perfGravCoef = perforationData.getField< fields::well::gravityCoefficient >(); arrayView1d< integer const > const & perfStatus = perforationData.getField< fields::perforation::perforationStatus >(); - + arrayView1d< localIndex const > const & perfWellElemIndex =perforationData.getField< fields::perforation::wellElementIndex >(); // 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 @@ -1164,6 +1653,7 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh resElementIndex, perfGravCoef, perfStatus, + perfWellElemIndex, wellElemGravCoef, wellElemPressure, wellElemTemp, @@ -1440,17 +1930,12 @@ void CompositionalMultiphaseWell::assembleWellAccumulationTerms( real64 const & 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 >(); + arrayView1d< real64 > const mixConnRate = subRegion.getField< fields::well::mixtureConnectionRate >(); localIndex rank_offset = dofManager.rankOffset(); forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) { @@ -1476,6 +1961,41 @@ 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(); + //bool wellClosed = wellControls.getWellStatus() != WellControls::Status::OPEN; + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + 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++ ) + { + globalIndex const rindex = localRow+i; + globalIndex const cindex =dofIndex + i; + localMatrix.template addToRow< serialAtomic >( rindex, + &cindex, + &unity, + 1 ); + localRhs[rindex] = 0.0; + } + } + } ); } @@ -2356,7 +2876,6 @@ CompositionalMultiphaseWell::applyWellSystemSolution( DofManager const & dofMana mesh, domain.getNeighbors(), true ); - } void @@ -2454,16 +2973,6 @@ void CompositionalMultiphaseWell::chopNegativeDensities( WellElementSubRegion & 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 ) @@ -2477,6 +2986,32 @@ void CompositionalMultiphaseWell::chopNegativeDensities( WellElementSubRegion & } } } ); + return; + WellControls const & wellControls = getWellControls( subRegion ); + if( isThermal() ) + { + real64 minTemp; + if( wellControls.isInjector() ) + minTemp =wellControls.getInjectionTemperature(); + // else + minTemp=280.0; + arrayView1d< real64 > const & wellElemTemperature = + subRegion.getField< well::temperature >(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) + { + if( wellElemGhostRank[iwelem] < 0 ) + { + if( wellElemTemperature[iwelem] < minTemp ) + { + GEOS_LOG_LEVEL_BY_RANK( logInfo::Solution, + GEOS_FMT( "{}: Bad temperature update, value set to injection temp = {} K", + wellElemTemperature[iwelem], minTemp ) ); + wellElemTemperature[iwelem] = minTemp; + } + } + } ); + } } @@ -2515,6 +3050,32 @@ void CompositionalMultiphaseWell::chopNegativeDensities( DomainPartition & domai } } } ); + return; + if( isThermal() ) + { + WellControls const & wellControls = getWellControls( subRegion ); + real64 minTemp; + if( wellControls.isInjector() ) + minTemp = wellControls.getInjectionTemperature(); + else + minTemp=280.0; + arrayView1d< real64 > const & wellElemTemperature = + subRegion.getField< well::temperature >(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) + { + if( wellElemGhostRank[iwelem] < 0 ) + { + if( wellElemTemperature[iwelem] < minTemp ) + { + // GEOS_LOG_LEVEL_BY_RANK( logInfo::Solution, + // GEOS_FMT( "{}: Bad temperature update, value set to injection temp = {} K", + // wellElemTemperature[iwelem], minTemp ) ); + wellElemTemperature[iwelem] = minTemp; + } + } + } ); + } } ); } ); @@ -2582,11 +3143,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() ) { @@ -3032,20 +3593,55 @@ bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, if( useEstimator ) { // create list of all constraints to solve + // note that initializeWells sets the initial constraint + // tjb reactive control schema to allow use to set if needed std::vector< WellConstraintBase * > constraintList; - WellConstraintBase * limitingConstraint = nullptr; + WellConstraintBase * limitingConstraint = wellControls.getCurrentConstraint(); if( wellControls.isProducer() ) { constraintList = wellControls.getProdRateConstraints(); + if( limitingConstraint->getControl() != ConstraintTypeId::BHP ) + { + { // remove from list and add BHP constraint + auto it = std::find( constraintList.begin(), constraintList.end(), limitingConstraint ); + if( it != constraintList.end() ) + { + constraintList.erase( it ); + } + if( wellControls.getMinBHPConstraint()->isConstraintActive() ) + { + constraintList.push_back( wellControls.getMinBHPConstraint() ); + } + } + } // Solve minimum bhp constraint first - limitingConstraint = wellControls.getMinBHPConstraint(); + if( wellControls.getMinBHPConstraint()->isConstraintActive() ) + { + // this is related to WHP option which introduces a new BHP constraint + limitingConstraint = wellControls.getMinBHPConstraint(); + } + else if( !constraintList.empty() ) + { + limitingConstraint = constraintList[0]; + } } else { constraintList = wellControls.getInjRateConstraints(); - // Solve maximum bhp constraint first - limitingConstraint = wellControls.getMaxBHPConstraint(); + // remove the limiting constraint from the list if present + { + if( limitingConstraint->getControl() != ConstraintTypeId::BHP ) + { // remove from list and add BHP constraint + auto it = std::find( constraintList.begin(), constraintList.end(), limitingConstraint ); + if( it != constraintList.end() ) + { + constraintList.erase( it ); + } + constraintList.push_back( wellControls.getMaxBHPConstraint() ); + } + } } + solveConstraint ( limitingConstraint, time_n, dt, cycleNumber, @@ -3061,11 +3657,14 @@ bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, 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 )) + if( constraint->isConstraintActive() && constraint->checkViolation( *limitingConstraint, time_n )) { limitingConstraint=constraint; wellControls.setControl( static_cast< WellControls::Control >(constraint->getControl()) ); // tjb old wellControls.setCurrentConstraint( limitingConstraint ); + GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), + " Well " << subRegion.getName() << " New Limiting Constraint " << constraint->getName() << " active " << constraint->isConstraintActive() << + " value " << constraint->getConstraintValue( time_n ) ); solveConstraint ( constraint, time_n, dt, cycleNumber, @@ -3085,6 +3684,21 @@ bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, } } + solveConstraint ( limitingConstraint, time_n, + dt, + cycleNumber, + coupledIterationNumber, + 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_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), " Well " << subRegion.getName() << " Limiting Constraint " << limitingConstraint->getName() << " " << limitingConstraint->bottomHolePressure() << " " << limitingConstraint->phaseVolumeRates() << " " << limitingConstraint->totalVolumeRate() << " " << limitingConstraint->massRate()); @@ -3097,7 +3711,10 @@ bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, { constraintList = wellControls.getProdRateConstraints(); // Solve minimum bhp constraint first - constraintList.insert( constraintList.begin(), wellControls.getMinBHPConstraint() ); + if( wellControls.getMinBHPConstraint()->isConstraintActive() ) + { + constraintList.insert( constraintList.begin(), wellControls.getMinBHPConstraint() ); + } } else { @@ -3132,10 +3749,9 @@ 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; wellControls.setControl( static_cast< WellControls::Control >(constraint->getControl()) ); // tjb old wellControls.setCurrentConstraint( constraint ); GEOS_LOG_RANK_IF ( getLogLevel() > 4 && subRegion.isLocallyOwned(), @@ -3150,7 +3766,7 @@ bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, } return true; } -void CompositionalMultiphaseWell::solveConstraint( WellConstraintBase *constraint, +void CompositionalMultiphaseWell::solveConstraint( WellConstraintBase *constraint, real64 const & time_n, real64 const & dt, integer const cycleNumber, @@ -3175,7 +3791,7 @@ void CompositionalMultiphaseWell::solveConstraint( WellConstraintBase *constra if( constraint->isConstraintActive() ) { wellControls.setControl( static_cast< WellControls::Control >(constraint->getControl()) ); // tjb old - wellControls.setCurrentConstraint( constraint ); + 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; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp index 02d15468503..dbb243b4108 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp @@ -329,7 +329,7 @@ class CompositionalMultiphaseWell : public WellSolverBase * @param matrix the system matrix * @param rhs the system right-hand side vector */ - virtual void assembleWellPressureRelations( real64 const & time_n, + virtual void assembleWellPressureRelations( real64 const & time_n, real64 const & dt, WellElementSubRegion const & subRegion, DofManager const & dofManager, @@ -344,6 +344,36 @@ class CompositionalMultiphaseWell : public WellSolverBase arrayView1d< real64 > const & localRhs ) override; + /** + * @brief apply a special treatment to the wells that are shut + * @param time_n the time at the previous converged 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 outputSingleWellDebug( real64 const time, + real64 const dt, + integer num_timesteps, + integer current_newton_iteration, + integer num_timestep_cuts, + MeshLevel & mesh, + WellElementSubRegion & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< const real64 > const & localRhs ) override; + + virtual void outputWellDebug( real64 const time, + real64 const dt, + integer num_timesteps, + integer current_newton_iteration, + integer num_timestep_cuts, + DomainPartition & domain, + 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 @@ -407,6 +437,9 @@ class CompositionalMultiphaseWell : public WellSolverBase } viewKeysCompMultiphaseWell; + void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) override; + + virtual void saveState( WellElementSubRegion & subRegion ) override; protected: virtual void postInputInitialization() override; @@ -415,7 +448,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 @@ -455,7 +488,12 @@ class CompositionalMultiphaseWell : public WellSolverBase void printRates( real64 const & time_n, real64 const & dt, DomainPartition & domain ) override; - + void printSegRates( real64 const & time_n, + real64 const & dt, + integer num_timesteps, + integer num_timestep_cuts, + integer current_newton_iteration, + DomainPartition & domain ); virtual bool evaluateConstraints( real64 const & time_n, real64 const & stepDt, integer const cycleNumber, @@ -474,14 +512,13 @@ 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( WellConstraintBase * constraint, + void solveConstraint( WellConstraintBase * constraint, real64 const & time_n, real64 const & dt, integer const cycleNumber, @@ -523,6 +560,7 @@ class CompositionalMultiphaseWell : public WellSolverBase /// index of the target phase, used to impose the phase rate constraint localIndex m_targetPhaseIndex; + bool m_wellDebugInit; }; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index b7f0b1f7d1a..747308e617a 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -765,9 +765,7 @@ 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 ); } ); } ); } @@ -1049,6 +1047,50 @@ void SinglePhaseWell::assembleVolumeBalanceTerms( DomainPartition const & GEOS_U // not implemented for single phase flow } +void SinglePhaseWell::outputSingleWellDebug( real64 const time, + real64 const dt, + integer num_timesteps, + integer current_newton_iteration, + integer num_timestep_cuts, + MeshLevel & mesh, + WellElementSubRegion & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< const real64 > const & localRhs ) +{ + GEOS_UNUSED_VAR( time ); + GEOS_UNUSED_VAR( dofManager ); + GEOS_UNUSED_VAR( localMatrix ); + GEOS_UNUSED_VAR( localRhs ); + GEOS_UNUSED_VAR( dt ); + GEOS_UNUSED_VAR( num_timesteps ); + GEOS_UNUSED_VAR( current_newton_iteration ); + GEOS_UNUSED_VAR( num_timestep_cuts ); + GEOS_UNUSED_VAR( mesh ); + GEOS_UNUSED_VAR( subRegion ); + +} + +void SinglePhaseWell::outputWellDebug( real64 const time, + real64 const dt, + integer num_timesteps, + integer current_newton_iteration, + integer num_timestep_cuts, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + GEOS_UNUSED_VAR( time ); + GEOS_UNUSED_VAR( dt ); + GEOS_UNUSED_VAR( num_timesteps ); + GEOS_UNUSED_VAR( current_newton_iteration ); + GEOS_UNUSED_VAR( num_timestep_cuts ); + GEOS_UNUSED_VAR( domain ); + GEOS_UNUSED_VAR( dofManager ); + GEOS_UNUSED_VAR( localMatrix ); + GEOS_UNUSED_VAR( localRhs ); +} void SinglePhaseWell::computePerforationRates( real64 const & time_n, real64 const & dt, DomainPartition & domain ) { @@ -1767,15 +1809,15 @@ void SinglePhaseWell::printRates( real64 const & time_n, } ); } -bool SinglePhaseWell::evaluateConstraints(real64 const & 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 & subRegion , - DofManager const & GEOS_UNUSED_PARAM( dofManager ) ) +bool SinglePhaseWell::evaluateConstraints( real64 const & 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 & subRegion, + DofManager const & GEOS_UNUSED_PARAM( dofManager ) ) { WellControls & wellControls = getWellControls( subRegion ); // create list of all constraints to process diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp index a0e2164fd6d..448fb85190b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp @@ -317,6 +317,25 @@ class SinglePhaseWell : public WellSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) override; + virtual void outputSingleWellDebug( real64 const time, + real64 const dt, + integer num_timesteps, + integer current_newton_iteration, + integer num_timestep_cuts, + MeshLevel & mesh, + WellElementSubRegion & subRegion, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< const real64 > const & localRhs ) override; + virtual void outputWellDebug( real64 const time, + real64 const dt, + integer num_timesteps, + integer current_newton_iteration, + integer num_timestep_cuts, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs )override; /* * @brief apply a special treatment to the wells that are shut * @param time_n the time at the previous converged time step @@ -330,6 +349,9 @@ class SinglePhaseWell : public WellSolverBase DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ); + + + virtual void saveState( WellElementSubRegion & subRegion ) override; struct viewKeyStruct : WellSolverBase::viewKeyStruct { static constexpr char const * dofFieldString() { return "singlePhaseWellVars"; } @@ -345,7 +367,6 @@ class SinglePhaseWell : public WellSolverBase virtual void initializePostInitialConditionsPreSubGroups() override; - void saveState( WellElementSubRegion & subRegion ); void printRates( real64 const & time_n, real64 const & dt, @@ -376,14 +397,14 @@ class SinglePhaseWell : public WellSolverBase WellElementSubRegion const & subRegion, ElementRegionManager const & elemManager ) override; - virtual bool evaluateConstraints( real64 const & time_n , + virtual bool evaluateConstraints( real64 const & 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 & subRegion , + WellElementSubRegion & subRegion, DofManager const & GEOS_UNUSED_PARAM( dofManager ) ) override; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp index 071c86482fb..003c86d466f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.cpp @@ -68,7 +68,7 @@ TableFunction * createConstraintScheduleTable( string const & tableName, WellConstraintBase::WellConstraintBase( string const & name, Group * const parent ) : Group( name, parent ), - m_isConstraintActive( true ), + m_isConstraintActive( 1 ), m_useScheduleTable( false ), m_constraintValue( 0 ), m_constraintScheduleTable( nullptr ), @@ -82,6 +82,13 @@ 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::constraintActiveString(), &m_isConstraintActive ). + setDefaultValue( 1 ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Flag to enable constraint. Currently only supported for injectors: \n" + " - If the flag is set to 1, constraint included in boundary condition selection. \n" + " - If the flag is set to 0, constraint excluded from boundary condition selection." ); + } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp index 4eaf2b82480..ea7a92a8efa 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellConstraintsBase.hpp @@ -177,6 +177,8 @@ class WellConstraintBase : public dataRepository::Group /// String key for the well constraint value static constexpr char const * constraintValueString() { return "constraintValue"; } + /// String key for the well constraint active flag + static constexpr char const * constraintActiveString() { return "constraintActive"; } } /// ViewKey struct for the WellControls class @@ -241,7 +243,7 @@ class WellConstraintBase : public dataRepository::Group protected: /// Constraint status - bool m_isConstraintActive; + integer m_isConstraintActive; /// Flag to indicate whether a schedule table should be generated for constraint value; bool m_useScheduleTable; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index 97b660dc407..754a528d0ad 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -42,7 +42,6 @@ WellControls::WellControls( string const & name, Group * const parent ) m_statusTable( nullptr ), m_wellOpen( false ), m_estimateSolution( false ), - m_constraintSwitch( true ), m_currentConstraint( nullptr ), m_wellStatus( WellControls::Status::OPEN ), m_regionAveragePressure( -1 ) @@ -99,7 +98,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 ) " ); -this->registerWrapper( viewKeyStruct::estimateWellSolutionString(), &m_estimateSolution ). + this->registerWrapper( viewKeyStruct::estimateWellSolutionString(), &m_estimateSolution ). setApplyDefaultValue( 0 ). setInputFlag( InputFlags::OPTIONAL ). setDescription( "Flag to esitmate well solution prior to coupled reservoir and well solve." ); @@ -131,45 +130,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 ); @@ -309,22 +308,14 @@ 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() ) { - getMinBHPConstraint()->setNextDtFromTables( currentTime, nextDt ); + if( getMinBHPConstraint() != nullptr ) + { + getMinBHPConstraint()->setNextDtFromTables( currentTime, nextDt ); + } for( auto const & constraint : m_productionRateConstraintList ) { constraint->setNextDtFromTables( currentTime, nextDt ); @@ -369,7 +360,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()) { @@ -384,7 +375,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() ) { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp index b3b232a0276..a44f3a15350 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp @@ -267,7 +267,7 @@ class WellControls : public dataRepository::Group */ void setControl( Control const & newControl ) { m_currentControl = newControl; } - /** + /** * @brief getter for esitmator switch * @return True if estimate well solution */ @@ -364,10 +364,6 @@ class WellControls : public dataRepository::Group 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; } @@ -488,19 +484,20 @@ 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; @@ -587,11 +584,6 @@ class WellControls : public dataRepository::Group /// 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 diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPropWriter.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPropWriter.hpp new file mode 100644 index 00000000000..cf0e4ae59b9 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPropWriter.hpp @@ -0,0 +1,609 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2018-2020 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2020 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2020 TotalEnergies + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file WellPropWriter.hpp + */ + +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLPROPWRITER_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLPROPWRITER_HPP + +#include + +#include "codingUtilities/Utilities.hpp" +#include "common/DataTypes.hpp" +#include "constitutive/fluid/multifluid/MultiFluidBase.hpp" +#include "constitutive/fluid/multifluid/MultiFluidFields.hpp" +#include "constitutive/fluid/multifluid/Layouts.hpp" +#include "physicsSolvers/fluidFlow/CompositionalMultiphaseBaseFields.hpp" +#include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" +#include "physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWellFields.hpp" +#include "physicsSolvers/fluidFlow/wells/WellSolverBaseFields.hpp" + +#include "mesh/PerforationFields.hpp" + +namespace geos +{ + +/******************************** WellPropWriter ********************************/ + +class WellPropWriter +{ +public: + template< bool cond, typename U > + using resolvedType = typename std::enable_if< cond, U >::type; + + struct prop_wrapper + { + virtual ~prop_wrapper() = default; + }; + + template< typename T > + struct typed_prop_wrapper : public prop_wrapper + { + typed_prop_wrapper( const T * prop ): m_prop( prop ){} + const T m_prop; + }; + + typedef std::multimap< std::type_index, prop_wrapper > type_info_to_prop_map; + + struct prop_writer + { + virtual void write_prop( const integer idx, std::ofstream & stream ) = 0; + }; + + struct perf_prop_writer + { + virtual void write_prop( const integer j, const integer er, const integer esr, const integer ei, std::ofstream & stream ) = 0; + }; + template< typename T > struct typed_1d_prop_writer : public prop_writer + { + typedef T value_type; + typedef typed_prop_wrapper< value_type > prop_wrapper_type; + + typed_1d_prop_writer( value_type & prop ): m_prop( prop ){} + value_type m_prop; + + virtual void write_prop( const integer idx, std::ofstream & stream ) + { + stream << "," << (m_prop)[idx]; + } + }; + template< typename T > struct typed_1d_perf_res_prop_writer : public perf_prop_writer + { + typedef T value_type; + typedef typed_prop_wrapper< value_type > prop_wrapper_type; + + typed_1d_perf_res_prop_writer( value_type const & prop ): m_prop( prop ){} + value_type const m_prop; + + virtual void write_prop( const integer g, const integer er, const integer esr, const integer ei, std::ofstream & stream ) + { + GEOS_UNUSED_VAR( g ); + stream << "," << m_prop[er][esr][ei]; + } + }; + template< typename T > struct typed_1d_perf_prop_writer : public perf_prop_writer + { + typedef T value_type; + typedef typed_prop_wrapper< value_type > prop_wrapper_type; + + typed_1d_perf_prop_writer( value_type const & prop ): m_prop( prop ){} + value_type const m_prop; + + virtual void write_prop( const integer j, const integer er, const integer esr, const integer ei, std::ofstream & stream ) + { + GEOS_UNUSED_VAR( er ); + GEOS_UNUSED_VAR( esr ); + GEOS_UNUSED_VAR( ei ); + stream << "," << m_prop[j]; + } + }; + template< typename T > struct typed_2d_perf_res_prop_writer1 : public perf_prop_writer + { + typedef T value_type; + typedef typed_prop_wrapper< value_type > prop_wrapper_type; + + typed_2d_perf_res_prop_writer1( value_type & prop, integer dim2 ): m_prop( prop ), m_Dim2( dim2 ){} + value_type const m_prop; + const integer m_Dim2; + + virtual void write_prop( const integer j, const integer er, const integer esr, const integer ei, std::ofstream & stream ) + { + GEOS_UNUSED_VAR( er ); + GEOS_UNUSED_VAR( esr ); + GEOS_UNUSED_VAR( ei ); + for( integer i=0; i struct typed_2d_perf_res_prop_writerf : public perf_prop_writer + { + typedef T value_type; + typedef typed_prop_wrapper< value_type > prop_wrapper_type; + + typed_2d_perf_res_prop_writerf( value_type & prop, integer dim2 ): m_prop( prop ), m_Dim2( dim2 ){} + value_type const m_prop; + const integer m_Dim2; + + virtual void write_prop( const integer g, const integer er, const integer esr, const integer ei, std::ofstream & stream ) + { + GEOS_UNUSED_VAR( g ); + for( integer i=0; i struct typed_2d_perf_res_prop_writer : public perf_prop_writer + { + typedef T value_type; + typedef typed_prop_wrapper< value_type > prop_wrapper_type; + + typed_2d_perf_res_prop_writer( value_type & prop, integer dim2 ): m_prop( prop ), m_Dim2( dim2 ){} + value_type const m_prop; + const integer m_Dim2; + + virtual void write_prop( const integer g, const integer er, const integer esr, const integer ei, std::ofstream & stream ) + { + GEOS_UNUSED_VAR( g ); + for( integer i=0; i struct typed_2d_prop_writer : public prop_writer + { + typedef T value_type; + typedef typed_prop_wrapper< value_type > prop_wrapper_type; + + typed_2d_prop_writer( value_type & prop, integer dim2 ): m_prop( prop ), m_Dim2( dim2 ){} + value_type m_prop; + const integer m_Dim2; + + virtual void write_prop( const integer idx, std::ofstream & stream ) + { + + for( integer i=0; i struct typed_f2d_prop_writer : public prop_writer + { + typedef T value_type; + typedef typed_prop_wrapper< value_type > prop_wrapper_type; + + typed_f2d_prop_writer( value_type & prop, integer dim2 ): m_prop( prop ), m_Dim2( dim2 ){} + value_type m_prop; + const integer m_Dim2; + + virtual void write_prop( const integer idx, std::ofstream & stream ) + { + for( integer i=0; i struct typed_f2d_perf_prop_writer : public perf_prop_writer + { + typedef T value_type; + typedef typed_prop_wrapper< value_type > prop_wrapper_type; + + typed_f2d_perf_prop_writer( value_type & prop, integer dim2 ): m_prop( prop ), m_Dim2( dim2 ){} + value_type m_prop; + const integer m_Dim2; + + virtual void write_prop( const integer g, const integer er, const integer esr, const integer ei, std::ofstream & stream ) + { + GEOS_UNUSED_VAR( g ); + for( integer i=0; i struct typed_3d_prop_writer : public prop_writer + { + typedef T value_type; + typedef typed_prop_wrapper< value_type > prop_wrapper_type; + + typed_3d_prop_writer( value_type & prop, integer dim2, integer dim3 ): m_prop( prop ), m_Dim2( dim2 ), m_Dim3( dim3 ){} + value_type m_prop; + const integer m_Dim2; + const integer m_Dim3; + + virtual void write_prop( const integer idx, std::ofstream & stream ) + { + for( integer i=0; i struct typed_f3d_prop_writer : public prop_writer + { + typedef T value_type; + typedef typed_prop_wrapper< value_type > prop_wrapper_type; + + typed_f3d_prop_writer( value_type & prop, integer dim2, integer dim3 ): m_prop( prop ), m_Dim2( dim2 ), m_Dim3( dim3 ){} + value_type m_prop; + const integer m_Dim2; + const integer m_Dim3; + + virtual void write_prop( const integer idx, std::ofstream & stream ) + { + for( integer i=0; i struct typed_f3d_perf_res_prop_writer : public perf_prop_writer + { + typedef T value_type; + typedef typed_prop_wrapper< value_type > prop_wrapper_type; + + typed_f3d_perf_res_prop_writer( value_type & prop, integer dim2, integer dim3 ): m_prop( prop ), m_Dim2( dim2 ), m_Dim3( dim3 ){} + value_type m_prop; + const integer m_Dim2; + const integer m_Dim3; + + virtual void write_prop( const integer g, const integer er, const integer esr, const integer ei, std::ofstream & stream ) + { + GEOS_UNUSED_VAR( g ); + for( integer i=0; i prop_to_writer_map; + typedef std::vector< prop_writer * > prop_to_writer_vec; + typedef std::vector< perf_prop_writer * > perfprop_to_writer_vec; + + WellPropWriter () + { + m_initialized=0; + } + WellPropWriter( WellPropWriter && ) = default; + ~WellPropWriter() + { + if( m_outputFile.is_open() ) + { + m_outputFile.close(); + } + if( m_perfOutputFile.is_open() ) + { + m_perfOutputFile.close(); + } + } + void initialize_perf( int myrank, const string & outputDir, const string & wellName, PerforationData const & perfData ) + { + m_perfOutputFile.open( outputDir + "/" + wellName + "_perf_"+ std::to_string( myrank )+".csv" ); + m_numPerforations=perfData.size(); + m_resElementRegion = perfData.getField< fields::perforation::reservoirElementRegion >(); + m_resElementSubRegion = perfData.getField< fields::perforation::reservoirElementSubRegion >(); + m_resElementIndex = perfData.getField< fields::perforation::reservoirElementIndex >(); + m_perfWellElemIndex = perfData.getField< fields::perforation::wellElementIndex >(); + m_perfResElemGlobalIndex = perfData.getField< fields::perforation::reservoirElementGlobalIndex >(); + } + void initialize_seg( int myrank, const string & outputDir, const string & wellName, + string_array phaseNames, + string_array componentNames, + WellElementSubRegion & subRegion ) + { + m_outputFile.open( outputDir + "/" + wellName + "_seg_" + std::to_string( myrank )+".csv" ); + m_numSegments = subRegion.size(); + m_phaseNames = phaseNames; + m_componentNames = componentNames; + m_numPhase = m_phaseNames.size(); + m_numComponent = m_componentNames.size(); + m_elemGhostRank = subRegion.ghostRank(); + m_globalWellElementIndex = subRegion.getGlobalWellElementIndex(); + } + + bool initialized() + { + return m_initialized == 1; + } + template< typename T > + void registerSegProp( std::string const & name, const T & prop ) + { + if( m_initialized == 0 ) + m_header.push_back( name ); + m_propWriterVec.push_back( new typed_1d_prop_writer( prop )); + } + template< typename T > + void registerPerfResProp( std::string const & name, const T & prop ) + { + if( m_initialized == 0 ) + m_perfHeader.push_back( name ); + m_perfPropWriterVec.push_back( new typed_1d_perf_res_prop_writer( prop )); + } + template< typename T > + void registerPerfComponentProp( std::string const & name, const T & prop ) + { + if( m_initialized == 0 ) + for( const auto & c : m_componentNames ) + { + m_perfHeader.push_back( name+"_"+c ); + } + m_perfPropWriterVec.push_back( new typed_2d_perf_res_prop_writer1( prop, m_numComponent )); + } + template< typename T > + void registerSeg2dProp( std::vector< std::string > const & name, const T & prop ) + { + if( m_initialized == 0 ) + for( const auto & c : name ) + { + m_header.push_back( c ); + } + m_propWriterVec.push_back( new typed_2d_prop_writer( prop, name.size() )); + } + + + template< typename T > + void registerPerf1dProp( std::vector< std::string > const & name, const T & prop ) + { + if( m_initialized == 0 ) + for( const auto & c : name ) + { + m_perfHeader.push_back( c ); + } + m_perfPropWriterVec.push_back( new typed_1d_perf_prop_writer( prop )); + } + template< typename T > + void registerPerf2dProp( std::vector< std::string > const & name, const T & prop ) + { + if( m_initialized == 0 ) + for( const auto & c : name ) + { + m_perfHeader.push_back( c ); + } + m_perfPropWriterVec.push_back( new typed_2d_perf_res_prop_writer1( prop, name.size() )); + } + template< typename T > + void registerPerfResComponentProp( std::string const & name, const T & prop ) + { + if( m_initialized == 0 ) + for( const auto & c : m_componentNames ) + { + m_perfHeader.push_back( name+"_"+c ); + } + m_perfPropWriterVec.push_back( new typed_2d_perf_res_prop_writer( prop, m_numComponent )); + } + template< typename T > + void registerPerfResPhaseComponentProp( std::string const & name, const T & prop ) + { + if( m_initialized == 0 ) + for( const auto & p : m_phaseNames ) + { + for( const auto & c : m_componentNames ) + { + m_perfHeader.push_back( name+"_"+p+"_"+c ); + } + } + m_perfPropWriterVec.push_back( new typed_f3d_perf_res_prop_writer( prop, m_numPhase, m_numComponent )); + } + template< typename T > + void registerSegPhasePropf( std::string const & name, const T & prop ) + { + if( m_initialized == 0 ) + for( const auto & p : m_phaseNames ) + { + m_header.push_back( name+"_"+p ); + } + m_propWriterVec.push_back( new typed_f2d_prop_writer( prop, m_numPhase )); + } + template< typename T > + void registerSegPhasePropDerf( std::string const & name, const std::vector< string > & der_names, const T & prop ) + { + if( m_initialized == 0 ) + for( const auto & p : m_phaseNames ) + { + for( const auto & d:der_names ) + m_header.push_back( name+"_"+p +"_"+d ); + } + + m_propWriterVec.push_back( new typed_f3d_prop_writer( prop, m_numPhase, der_names.size())); + + } + template< typename T > + void registerSegPhasePropDer( std::string const & name, const std::vector< string > & der_names, const T & prop ) + { + if( m_initialized == 0 ) + for( const auto & p : m_phaseNames ) + { + for( const auto & d:der_names ) + m_header.push_back( name+"_"+p +"_"+d ); + } + m_propWriterVec.push_back( new typed_3d_prop_writer( prop, m_numPhase, der_names.size())); + } + template< typename T > + void registerSegPhaseProp( std::string const & name, const T & prop ) + { + if( m_initialized == 0 ) + for( const auto & p : m_phaseNames ) + { + m_header.push_back( name+"_"+p ); + } + + m_propWriterVec.push_back( new typed_2d_prop_writer( prop, m_numPhase )); + } + template< typename T > + void registerPerfResPhaseProp( std::string const & name, const T & prop ) + { + if( m_initialized == 0 ) + for( const auto & p : m_phaseNames ) + { + m_perfHeader.push_back( name+"_"+p ); + } + + m_perfPropWriterVec.push_back( new typed_2d_perf_res_prop_writer( prop, m_numPhase )); + } + template< typename T > + void registerPerfResPhasePropf( std::string const & name, const T & prop ) + { + if( m_initialized == 0 ) + for( const auto & p : m_phaseNames ) + { + m_perfHeader.push_back( name+"_"+p ); + } + + m_perfPropWriterVec.push_back( new typed_2d_perf_res_prop_writerf( prop, m_numPhase )); + } + template< typename T > + void registerPerfPhasePropf( std::string const & name, const T & prop ) + { + if( m_initialized == 0 ) + for( const auto & p : m_phaseNames ) + { + m_perfHeader.push_back( name+"_"+p ); + } + + m_perfPropWriterVec.push_back( new typed_f2d_perf_prop_writer( prop, m_numPhase )); + } + template< typename T > + void registerPerfComponentPropf( std::string const & name, const T & prop ) + { + if( m_initialized == 0 ) + for( const auto & p : m_componentNames ) + { + m_perfHeader.push_back( name+"_"+p ); + } + + m_perfPropWriterVec.push_back( new typed_f2d_perf_prop_writer( prop, m_numComponent )); + } + + template< typename T > + void registerSegComponentProp( std::string const & name, const T & prop ) + { + if( m_initialized == 0 ) + for( const auto & c : m_componentNames ) + { + m_header.push_back( name+"_"+c ); + } + m_propWriterVec.push_back( new typed_2d_prop_writer( prop, m_numComponent )); + } + template< typename T > + void registerSegPhaseComponentProp( std::string const & name, const T & prop ) + { + if( m_initialized == 0 ) + for( const auto & p : m_phaseNames ) + { + for( const auto & c : m_componentNames ) + { + m_header.push_back( name+"_"+p+"_"+c ); + } + } + m_propWriterVec.push_back( new typed_3d_prop_writer( prop, m_numPhase, m_numComponent )); + } + template< typename T > + void registerSegPhaseComponentPropf( std::string const & name, const T & prop ) + { + if( m_initialized == 0 ) + for( const auto & p : m_phaseNames ) + { + for( const auto & c : m_componentNames ) + { + m_header.push_back( name+"_"+p+"_"+c ); + } + } + m_propWriterVec.push_back( new typed_f3d_prop_writer( prop, m_numPhase, m_numComponent )); + } + void write( real64 time, real64 dt, integer cycle, integer subevent, integer timeStep, integer newtonIter, integer numTimeStepCuts ) + { + if( m_initialized == 0 ) + { + m_outputFile << "Time,Dt,Cycle,SubEvent,TimeStep,NewtonIteration,TimeStepCuts,Element"; + for( auto i :m_header ) + { + m_outputFile << "," << i; + } + m_outputFile << std::endl; + // for perf data + m_perfOutputFile << "Time,Dt,Cycle,SubEvent,TimeStep,NewtonIteration,TimeStepCuts,ResElement,WellElement"; + for( auto i :m_perfHeader ) + { + m_perfOutputFile << "," << i; + } + m_perfOutputFile << std::endl; + m_initialized = 1; + } + + for( integer j =0; j < m_numSegments; j++ ) + { + if( m_elemGhostRank[j] < 0 ) + { + m_outputFile << time << "," << dt << "," << cycle << "," << subevent << "," << timeStep << "," << newtonIter << "," << numTimeStepCuts<<","<write_prop( j, m_outputFile ); + cntr=cntr+1; + } + m_outputFile << std::endl; + } + } + + for( integer j =0; j < m_numPerforations; j++ ) + { + localIndex const iwelem = m_perfWellElemIndex[j]; + if( m_elemGhostRank[iwelem] < 0 ) + { + localIndex const er = m_resElementRegion[j]; + localIndex const esr = m_resElementSubRegion[j]; + localIndex const ei = m_resElementIndex[j]; + m_perfOutputFile << time << "," << dt << "," << cycle << "," << subevent << "," << timeStep << "," << newtonIter << "," << numTimeStepCuts<<","<write_prop( j, er, esr, ei, m_perfOutputFile ); + } + m_perfOutputFile << std::endl; + } + } + m_propWriterVec.clear(); + m_perfPropWriterVec.clear(); + } + +protected: + integer m_initialized; + string_array m_phaseNames; + string_array m_componentNames; + integer m_numSegments; + integer m_numComponent; + integer m_numPhase; + + std::vector< string > m_header; + std::ofstream m_outputFile; + prop_to_writer_vec m_propWriterVec; + + // perforation data + integer m_numPerforations; + arrayView1d< localIndex const > m_resElementRegion; + arrayView1d< localIndex const > m_resElementSubRegion; + arrayView1d< localIndex const > m_resElementIndex; + arrayView1d< localIndex const > m_perfWellElemIndex; + arrayView1d< globalIndex const > m_perfResElemGlobalIndex; + + std::vector< string > m_perfHeader; + std::ofstream m_perfOutputFile; + perfprop_to_writer_vec m_perfPropWriterVec; + + /// Global index of local element + arrayView1d< globalIndex const > m_globalWellElementIndex; + arrayView1d< integer const > m_elemGhostRank; +}; + + +} // end namespace geos + +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_PERFORATIONFLUXLKERNELS_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp index f5ecf916397..6cdcc152374 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp @@ -44,7 +44,11 @@ WellSolverBase::WellSolverBase( string const & name, m_isThermal( 0 ), m_ratesOutputDir( joinPath( OutputBase::getOutputDirectory(), name + "_rates" ) ), m_keepVariablesConstantDuringInitStep( false ), - + m_writeSegDebug( 0 ), + m_globalNumTimeSteps( -1 ), + m_currentDt( -1.0 ), + my_ctime( 0 ), + m_nextDt( -1 ), m_useNewCode( true ) { registerWrapper( viewKeyStruct::isThermalString(), &m_isThermal ). @@ -70,6 +74,10 @@ WellSolverBase::WellSolverBase( string const & name, setInputFlag( InputFlags::OPTIONAL ). setDescription( "Use new code" ); + this->registerWrapper( viewKeyStruct::writeSegDebugFlagString(), &m_writeSegDebug ). + setApplyDefaultValue( 0 ). + setInputFlag( dataRepository::InputFlags::OPTIONAL ). + setDescription( "Write well seg/perf debug into CSV files" ); addLogLevel< logInfo::WellControl >(); } @@ -110,6 +118,13 @@ void WellSolverBase::postInputInitialization() m_numDofPerResElement = m_isThermal ? m_numComponents + 1: m_numComponents; // 1 pressure + temp if thermal + if( m_writeSegDebug > 0 ) + { + if( m_writeCSV == 0 ) + { + m_writeCSV=1; + } + } // create dir for rates output if( m_writeCSV > 0 ) { @@ -356,8 +371,8 @@ void WellSolverBase::selectWellConstraint( real64 const & time_n, GEOS_UNUSED_VAR( dt ); GEOS_UNUSED_VAR( coupledIterationNumber ); - setupWellDofs( domain ); - integer cycleNumber=0; + setupWellDofs( domain ); + integer cycleNumber=0; forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const & meshBodyName, MeshLevel & meshLevel, string_array const & regionNames ) @@ -410,9 +425,6 @@ void WellSolverBase::selectWellConstraint( real64 const & time_n, //GEOS_LOG_LEVEL( logInfo::Fields, oss.str()) } - - wellControls.setConstraintSwitch( false ); - evaluateConstraints( time_n, dt, cycleNumber, @@ -489,12 +501,9 @@ void WellSolverBase::assembleWellSystem( real64 const time_n, 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 ); - } + 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 ); @@ -547,9 +556,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 ); } ); } ); } @@ -560,8 +567,80 @@ void WellSolverBase::assembleSystem( real64 const time, // 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 ); + + // sort out how this work with well estimator + auto iterInfo = currentIter( time, dt ); + outputWellDebug( time, dt, std::get< 0 >( iterInfo ), std::get< 1 >( iterInfo ), std::get< 2 >( iterInfo ), + domain, dofManager, localMatrix, localRhs ); + + + my_ctime=my_ctime+1; + } +std::tuple< integer, integer, integer > +WellSolverBase::currentIter( real64 const time, real64 const dt ) +{ + if( isEqual( m_currentDt, -1.0 ) ) + { + m_globalNumTimeSteps=0; + m_currentTime=time; + m_prevTime=time; + m_currentDt=dt; + m_prevDt=dt; + m_numTimeStepCuts=0; + m_currentNewtonIteration=0; + } + else + { + if( !isEqual( time, m_currentTime ) ) + { + m_globalNumTimeSteps++; + m_prevTime=m_currentTime; + m_prevDt=m_currentDt; + m_currentTime=time; + m_currentDt=dt; + m_currentNewtonIteration=0; + m_numTimeStepCuts=0; + } + else + { + if( dt < m_currentDt ) + { + // timestep cut + m_globalNumTimeSteps++; + m_prevTime=m_currentTime; + m_prevDt=m_currentDt; + m_currentTime=time; + m_currentDt=dt; + m_currentNewtonIteration=0; + m_numTimeStepCuts++; + m_currentNewtonIteration=0; + } + /* + else if ( isEqual(dt,m_currentDt ) ) + { + // next timestep + m_globalNumTimeSteps++; + m_prevTime=m_currentTime; + m_prevDt=m_currentDt; + m_currentTime=time; + m_currentDt=dt; + m_currentNewtonIteration=0; + m_numTimeStepCuts=0; + m_currentNewtonIteration=0; + }*/ + else + { + // continuation of current timestep + m_currentNewtonIteration++; + } + } + } + + return std::tuple< integer, integer, integer >( m_globalNumTimeSteps, m_numTimeStepCuts, m_currentNewtonIteration ); + +} void WellSolverBase::initializePostInitialConditionsPreSubGroups() { PhysicsSolverBase::initializePostInitialConditionsPreSubGroups(); @@ -706,9 +785,9 @@ bool WellSolverBase::solveNonlinearSystem( real64 const & time_n, for( newtonIter = 0; newtonIter < maxNewtonIter; ++newtonIter ) { - - GEOS_LOG_LEVEL_RANK_0( logInfo::NonlinearSolver, - GEOS_FMT( " Well: {} Est Attempt: {:2}, ConfigurationIter: {:2}, NewtonIter: {:2}", subRegion.getName(), dtAttempt, configurationLoopIter, newtonIter )); + if( m_nonlinearSolverParameters.getLogLevel() > 4 ) + GEOS_LOG_LEVEL_RANK_0( logInfo::NonlinearSolver, + GEOS_FMT( " Well: {} Est Attempt: {:2}, ConfigurationIter: {:2}, NewtonIter: {:2}", subRegion.getName(), dtAttempt, configurationLoopIter, newtonIter )); { Timer timer( m_timers["assemble"] ); @@ -752,22 +831,28 @@ bool WellSolverBase::solveNonlinearSystem( real64 const & time_n, m_assemblyCallback( m_localMatrix, std::move( localRhsCopy ) ); } } - // outputSingleWellDebug( time_n, stepDt, 0, newtonIter, 0, - // mesh, subRegion, dofManager, m_localMatrix.toViewConstSizes(), m_rhs.values() ); + + outputSingleWellDebug( time_n, stepDt, 0, newtonIter, 0, + mesh, subRegion, dofManager, m_localMatrix.toViewConstSizes(), m_rhs.values() ); real64 residualNorm = 0; { Timer timer( m_timers["convergence check"] ); // get residual norm residualNorm = calculateWellResidualNorm( time_n, stepDt, subRegion, dofManager, m_rhs.values() ); - GEOS_LOG_LEVEL_RANK_0( logInfo::Convergence, - GEOS_FMT( " ( R ) = ( {:4.2e} )", residualNorm ) ); + if( m_nonlinearSolverParameters.getLogLevel() > 4 ) + GEOS_LOG_LEVEL_RANK_0( logInfo::Convergence, + GEOS_FMT( " ( R ) = ( {:4.2e} )", residualNorm ) ); } //auto iterInfo = currentIter( time_n, dt ); //outputSingleWellDebug( time_n, stepDt, 0, newtonIter, 0, // mesh, subRegion, dofManager, m_localMatrix.toViewConstSizes(), m_rhs.values() ); // if the residual norm is less than the Newton tolerance we denote that we have // converged and break from the Newton loop immediately. + std::cout << " Well: " << subRegion.getName() << " Est Attempt: " << dtAttempt + << ", ConfigurationIter: " << configurationLoopIter + << ", NewtonIter: " << newtonIter + << ", Residual Norm: " << residualNorm << std::endl; if( residualNorm < newtonTol && newtonIter >= minNewtonIter ) { isNewtonConverged = true; @@ -779,10 +864,11 @@ bool WellSolverBase::solveNonlinearSystem( real64 const & time_n, if( residualNorm > m_nonlinearSolverParameters.m_maxAllowedResidualNorm ) { string const maxAllowedResidualNormString = NonlinearSolverParameters::viewKeysStruct::maxAllowedResidualNormString(); - GEOS_LOG_LEVEL_RANK_0( logInfo::Convergence, - GEOS_FMT( " The residual norm is above the {} of {}. Newton loop terminated.", - maxAllowedResidualNormString, - m_nonlinearSolverParameters.m_maxAllowedResidualNorm ) ); + if( m_nonlinearSolverParameters.getLogLevel() > 4 ) + GEOS_LOG_LEVEL_RANK_0( logInfo::Convergence, + GEOS_FMT( " The residual norm is above the {} of {}. Newton loop terminated.", + maxAllowedResidualNormString, + m_nonlinearSolverParameters.m_maxAllowedResidualNorm ) ); isNewtonConverged = false; break; } @@ -790,7 +876,7 @@ bool WellSolverBase::solveNonlinearSystem( real64 const & time_n, // do line search in case residual has increased - if( false && m_nonlinearSolverParameters.m_lineSearchAction != NonlinearSolverParameters::LineSearchAction::None + if( m_nonlinearSolverParameters.m_lineSearchAction != NonlinearSolverParameters::LineSearchAction::None && residualNorm > lastResidual * m_nonlinearSolverParameters.m_lineSearchResidualFactor && newtonIter >= m_nonlinearSolverParameters.m_lineSearchStartingIteration ) { @@ -832,14 +918,16 @@ bool WellSolverBase::solveNonlinearSystem( real64 const & time_n, { if( m_nonlinearSolverParameters.m_lineSearchAction == NonlinearSolverParameters::LineSearchAction::Attempt ) { - GEOS_LOG_LEVEL_RANK_0( logInfo::LineSearch, - " Line search failed to produce reduced residual. Accepting iteration." ); + if( m_nonlinearSolverParameters.getLogLevel() > 4 ) + GEOS_LOG_LEVEL_RANK_0( logInfo::LineSearch, + " Line search failed to produce reduced residual. Accepting iteration." ); } else if( m_nonlinearSolverParameters.m_lineSearchAction == NonlinearSolverParameters::LineSearchAction::Require ) { // if line search failed, then break out of the main Newton loop. Timestep will be cut. - GEOS_LOG_LEVEL_RANK_0( logInfo::LineSearch, - " Line search failed to produce reduced residual. Exiting Newton Loop." ); + if( m_nonlinearSolverParameters.getLogLevel() > 4 ) + GEOS_LOG_LEVEL_RANK_0( logInfo::LineSearch, + " Line search failed to produce reduced residual. Exiting Newton Loop." ); break; } } @@ -888,14 +976,15 @@ bool WellSolverBase::solveNonlinearSystem( real64 const & time_n, // Compute the scaling factor for the Newton update scaleFactor = scalingForWellSystemSolution( subRegion, dofManager, m_solution.values() ); - - GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, - GEOS_FMT( " {}: Global solution scaling factor = {}", getName(), scaleFactor ) ); + if( m_nonlinearSolverParameters.getLogLevel() > 4 ) + GEOS_LOG_LEVEL_RANK_0( logInfo::Solution, + GEOS_FMT( " {}: Global solution scaling factor = {}", getName(), scaleFactor ) ); if( !checkWellSystemSolution( subRegion, dofManager, m_solution.values(), scaleFactor ) ) { // TODO try chopping (similar to line search) - GEOS_LOG_RANK_0( GEOS_FMT( " {}: Solution check failed. Newton loop terminated.", getName()) ); + if( m_nonlinearSolverParameters.getLogLevel() > 4 ) + GEOS_LOG_RANK_0( GEOS_FMT( " {}: Solution check failed. Newton loop terminated.", getName()) ); break; } @@ -906,14 +995,14 @@ bool WellSolverBase::solveNonlinearSystem( real64 const & time_n, { Timer timer( m_timers["update state"] ); -// update non-primary variables (constitutive models) - + // update derived variables (constitutive models) updateWellState( subRegion ); } lastResidual = residualNorm; + std::cout << "lastResidual " << lastResidual << std::endl; } - + std::cout << "isNewtonConverged " << isNewtonConverged << std::endl; return isNewtonConverged; } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp index 64fcf29c5b9..d987ff2da55 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp @@ -21,6 +21,7 @@ #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_WELLS_WELLSOLVERBASE_HPP_ #include "physicsSolvers/PhysicsSolverBase.hpp" +#include "physicsSolvers/fluidFlow/wells/WellPropWriter.hpp" namespace geos { @@ -165,9 +166,9 @@ class WellSolverBase : public PhysicsSolverBase DomainPartition & domain ); - void setupWellDofs( DomainPartition & domain ); - - void setupWellSystem ( DomainPartition & domain, + void setupWellDofs( DomainPartition & domain ); + + void setupWellSystem ( DomainPartition & domain, DofManager & dofManager, CRSMatrix< real64, globalIndex > & localMatrix, ParallelVector & rhs, @@ -305,14 +306,33 @@ class WellSolverBase : public PhysicsSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) = 0; + virtual void outputSingleWellDebug( real64 const GEOS_UNUSED_PARAM( time ), + real64 const GEOS_UNUSED_PARAM( dt ), + integer GEOS_UNUSED_PARAM( num_timesteps ), + integer GEOS_UNUSED_PARAM( current_newton_iteration ), + integer GEOS_UNUSED_PARAM( num_timestep_cuts ), + MeshLevel & GEOS_UNUSED_PARAM( mesh ), + WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ), + DofManager const & GEOS_UNUSED_PARAM( dofManager ), + CRSMatrixView< real64, globalIndex const > const & GEOS_UNUSED_PARAM( localMatrix ), + arrayView1d< const real64 > const & GEOS_UNUSED_PARAM( localRhs ) ) = 0; + + virtual void outputWellDebug( real64 const time, + real64 const dt, + integer num_timesteps, + integer current_newton_iteration, + integer num_timestep_cuts, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + 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 & subRegion ) = 0; virtual void updateState( DomainPartition & domain ) override; - + virtual void saveState( WellElementSubRegion & subRegion ) = 0; /** * @brief Recompute all dependent quantities from primary variables (including constitutive * models) @@ -369,6 +389,9 @@ class WellSolverBase : public PhysicsSolverBase ElementRegionManager & elementRegionManager, WellElementSubRegion & subregion, DofManager const & dofManager ); + + virtual void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) = 0; + /** * @brief Function to perform line search * @param time_n time at the beginning of the step @@ -431,11 +454,14 @@ 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 * writeSegDebugFlagString() { return "writeSegDebug"; } static constexpr char const * useNewCodeString() { return "useNewCode"; } static constexpr char const * fluidNamesString() { return "fluidNames"; } }; + + std::tuple< integer, integer, integer > currentIter( real64 const time, real64 const dt ); private: /** @@ -457,7 +483,6 @@ 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 @@ -473,14 +498,14 @@ class WellSolverBase : public PhysicsSolverBase real64 const & dt, DomainPartition & domain ) = 0; - virtual bool evaluateConstraints( real64 const & GEOS_UNUSED_PARAM( time_n ) , + 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 ) , + WellElementSubRegion & GEOS_UNUSED_PARAM( subRegion ), DofManager const & GEOS_UNUSED_PARAM( dofManager ) ) { return false;}; @@ -512,6 +537,21 @@ class WellSolverBase : public PhysicsSolverBase /// flag to freeze the initial state during initialization in coupled problems bool m_keepVariablesConstantDuringInitStep; + /// flag to write detailed segment properties + integer m_writeSegDebug; + + integer m_globalNumTimeSteps; + real64 m_currentTime; + real64 m_currentDt; + real64 m_prevTime; + real64 m_prevDt; + integer m_numTimeStepCuts; + integer m_currentNewtonIteration; + + std::map< std::string, WellPropWriter > m_wellPropWriter; + std::map< std::string, WellPropWriter > m_wellPropWriter_eot; + + /// name of the fluid constitutive model used as a reference for component/phase description string m_referenceFluidModelName; @@ -524,11 +564,12 @@ class WellSolverBase : public PhysicsSolverBase /// @details This DofManager is used to store the DOF numbers for the estimator /// @note This DofManager is used in the assembly of the estimators linear system std::map< std::string, DofManager > m_estimatorDoFManager; + integer my_ctime; //tjb - + real64 m_nextDt; integer m_useNewCode; - integer my_ctime; //tjb + }; } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp index 0a78824d6e9..57349d508a9 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp @@ -420,6 +420,7 @@ PresTempCompFracInitializationKernel:: arrayView1d< localIndex const > const & resElementIndex, arrayView1d< real64 const > const & perfGravCoef, arrayView1d< integer const > const & perfStatus, + arrayView1d< localIndex const > const perfWellElemIndex, arrayView1d< real64 const > const & wellElemGravCoef, arrayView1d< real64 > const & wellElemPres, arrayView1d< real64 > const & wellElemTemp, @@ -432,9 +433,10 @@ PresTempCompFracInitializationKernel:: real64 const initialPresCoef = wellControls.getInitialPressureCoefficient(); WellControls::Control const currentControl = wellControls.getControl(); bool const isProducer = wellControls.isProducer(); - - - + localIndex const nLocalSeg = wellElemPres.size(); + array1d< real64 > segTemp; + GEOS_UNUSED_VAR( perfWellElemIndex ); + segTemp.resize( nLocalSeg ); // Step 1: we loop over all the perforations on this rank to compute the following quantities: // - Sum of total mass densities over the perforated reservoir elements // - Sum of the temperatures over the perforated reservoir elements @@ -448,7 +450,7 @@ PresTempCompFracInitializationKernel:: RAJA::ReduceSum< parallelDeviceReduce, real64 > sumCompFrac[MAX_NUM_COMP]{}; RAJA::ReduceMin< parallelDeviceReduce, real64 > localMinGravCoefDiff( 1e9 ); - forAll< parallelDevicePolicy<> >( perforationSize, [=] GEOS_HOST_DEVICE ( localIndex const iperf ) + forAll< parallelDevicePolicy<> >( perforationSize, [&] GEOS_HOST_DEVICE ( localIndex const iperf ) { if( perfStatus[iperf] ) { @@ -457,7 +459,9 @@ PresTempCompFracInitializationKernel:: localIndex const er = resElementRegion[iperf]; localIndex const esr = resElementSubRegion[iperf]; localIndex const ei = resElementIndex[iperf]; - + //localIndex const wi = perfWellElemIndex[iperf]; + //std::cout << "perf " << iperf << " maps to well elem " << wi << std::endl; + //segTemp[wi] = resTemp[er][esr][ei]; // save the min gravCoef difference between the reference depth and the perforation depth (times g) localMinGravCoefDiff.min( LvArray::math::abs( refWellElemGravCoef - perfGravCoef[iperf] ) ); @@ -482,6 +486,16 @@ PresTempCompFracInitializationKernel:: } } } ); +#if 0 + for( integer i=nLocalSeg-2; i>-1; --i ) + { + std::cout << "segTemp[" << i << "] = " << segTemp[i] << std::endl; + if( segTemp[i] == 0.0 ) + { + segTemp[i] = segTemp[i+1]; + } + } +#endif real64 const minGravCoefDiff = MpiWrapper::min( localMinGravCoefDiff.get() ); integer totalOpenPerfs = MpiWrapper::sum( numOpenPerfs.get() ); @@ -500,7 +514,6 @@ PresTempCompFracInitializationKernel:: { // use average temperature from reservoir avgTemp = MpiWrapper::sum( sumTemp.get() ) / totalOpenPerfs; - // use average comp frac from reservoir for( integer ic = 0; ic < numComps; ++ic ) { @@ -552,6 +565,9 @@ PresTempCompFracInitializationKernel:: if( isZero( gravCoefDiff - minGravCoefDiff ) ) { localRefPres.min( alpha * resPres[er][esr][ei] + avgTotalMassDens * ( refWellElemGravCoef - perfGravCoef[iperf] ) ); + //localRefPres.min( resPres[er][esr][ei] ); + //std::cout << "perf " << iperf << " alpha " << alpha << " resPres " << resPres[er][esr][ei] << " estimated refPres " << + // refWellElemGravCoef << " " << perfGravCoef[iperf] << std::endl; } } } ); @@ -574,8 +590,11 @@ PresTempCompFracInitializationKernel:: forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) { wellElemPres[iwelem] = refPres + avgTotalMassDens * ( wellElemGravCoef[iwelem] - refWellElemGravCoef ); + //wellElemPres[iwelem] = refPres ; wellElemTemp[iwelem] = avgTemp; - +#if 0 + wellElemTemp[iwelem] = segTemp[iwelem]; +#endif real64 sumCompFracForCheck = 0.0; for( integer ic = 0; ic < numComps; ++ic ) { @@ -608,7 +627,9 @@ PresTempCompFracInitializationKernel:: GEOS_THROW_IF( foundInconsistentCompFrac.get() == 1, wellControls.getDataContext() << "Invalid well initialization, inconsistent component fractions were found.", InputError ); - + std::cout << wellControls.getName() << " initialized with reference pressure " << refPres + << ", average temperature " << avgTemp + << ", average total mass density " << avgTotalMassDens << std::endl; } @@ -654,7 +675,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 +692,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 { @@ -691,6 +723,7 @@ RateInitializationKernel:: { forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) { + std::cout << "rate est " << iwelem << " " << constraintVal << std::endl; connRate[iwelem] = constraintVal * totalDens[iwelem][0]; } ); } @@ -701,6 +734,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 ); + } ); + } } } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp index b01d8adf0ab..9a1506b306f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp @@ -292,6 +292,7 @@ struct PresTempCompFracInitializationKernel arrayView1d< localIndex const > const & resElementIndex, arrayView1d< real64 const > const & perfGravCoef, arrayView1d< integer const > const & perfState, + arrayView1d< localIndex const > const perfWellElemIndex, arrayView1d< real64 const > const & wellElemGravCoef, arrayView1d< real64 > const & wellElemPres, arrayView1d< real64 > const & wellElemTemp, @@ -525,7 +526,8 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa { if( m_isProducer ) { - m_targetBHP = wellControls.getMinBHPConstraint()->getConstraintValue( time ); + if( wellControls.getMinBHPConstraint()->isConstraintActive()) + m_targetBHP = wellControls.getMinBHPConstraint()->getConstraintValue( time ); // 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 @@ -538,7 +540,7 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa { m_targetBHP = wellControls.getMaxBHPConstraint()->getConstraintValue( time ); - // Note this assumes that there is only one rate constraint + // tjb 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) @@ -1151,7 +1153,18 @@ class ElementBasedAssemblyKernel stack.localResidual[numRows-1]=0.0; } } + /* tjb iso + for( integer i=0; i < numComp+1+IS_THERMAL; i++ ) + { + stack.localJacobian[numRows-1][i] = 0.0; + } + // constant Temperature + for( integer i=0; i < numComp+1+IS_THERMAL; i++ ) + stack.localJacobian[i][numRows-1] = 0.0; + stack.localJacobian[numRows-1][numRows-1] = 1.0; + stack.localResidual[numRows-1]=0.0; + */ if( m_kernelFlags.isSet( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ) ) { // apply equation/variable change transformation to the component mass balance equations @@ -1620,13 +1633,11 @@ class FaceBasedAssemblyKernel // derivative with respect to upstream pressure stack.localFluxJacobian[TAG::NEXT * NC +ic][CP_Deriv::dP] = dt * dCompFlux[ic][WJ_COFFSET::dP]; stack.localFluxJacobian[TAG::CURRENT * NC+ ic][CP_Deriv::dP] = -dt * dCompFlux[ic][WJ_COFFSET::dP]; - if constexpr ( IS_THERMAL ) { stack.localFluxJacobian[TAG::NEXT * NC +ic][CP_Deriv::dT] = dt * dCompFlux[ic][WJ_COFFSET::dT]; stack.localFluxJacobian[TAG::CURRENT * NC +ic][CP_Deriv::dT] = -dt * dCompFlux[ic][WJ_COFFSET::dT]; } - // derivatives with respect to upstream component densities for( integer jdof = 0; jdof < NC; ++jdof ) { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/PerforationFluxKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/PerforationFluxKernels.hpp index e8862990a2d..d618272de94 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/PerforationFluxKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/PerforationFluxKernels.hpp @@ -218,7 +218,6 @@ class PerforationFluxKernel multiplier[TAG::WELL] = -1.0; real64 const gravD = ( m_perfGravCoef[iperf] - m_wellElemGravCoef[iwelem] ); - pres[TAG::WELL] += m_wellElemTotalMassDens[iwelem] * gravD; // Note LHS uses CP_Deriv while RHS uses Deriv !!! dPres[TAG::WELL][CP_Deriv::dP] += m_dWellElemTotalMassDens[iwelem][Deriv::dP] * gravD; @@ -332,7 +331,6 @@ class PerforationFluxKernel // increment component fluxes for( integer ic = 0; ic < NC; ++ic ) { - // Note this needs to be uncommented out m_compPerfRate[iperf][ic] += flux * m_resPhaseCompFrac[er][esr][ei][0][ip][ic]; dCompFrac[CP_Deriv::dP] = m_dResPhaseCompFrac[er][esr][ei][0][ip][ic][Deriv::dP]; if constexpr (IS_THERMAL) @@ -353,10 +351,6 @@ class PerforationFluxKernel m_dCompPerfRate[iperf][TAG::WELL][ic][jc] += dFlux[TAG::WELL][jc] * m_resPhaseCompFrac[er][esr][ei][0][ip][ic]; } } - if constexpr ( IS_THERMAL ) - { - fluxKernelOp( iwelem, er, esr, ei, ip, potDiff, flux, dFlux ); - } } // end resevoir is upstream phase loop @@ -480,11 +474,12 @@ class PerforationFluxKernel m_dCompPerfRate[iperf][TAG::WELL][ic][CP_Deriv::dC+jc] += m_dWellElemCompFrac_dCompDens[iwelem][ic][jc] * flux; } } - if constexpr ( IS_THERMAL ) - { - fluxKernelOp( iwelem, er, esr, ei, -1, potDiff, flux, dFlux ); - } + } // end upstream + if constexpr ( IS_THERMAL ) + { + fluxKernelOp( iwelem, er, esr, ei, potDiff, dPotDiff, flux, dFlux ); + } } /** * @brief Performs the kernel launch @@ -607,9 +602,21 @@ class PerforationFluxKernel : public isothermalPerforationFluxKernels::Perforati public: using Base = isothermalPerforationFluxKernels::PerforationFluxKernel< NC, NP, IS_THERMAL >; - using Base::m_resPhaseCompFrac; - using Base::m_dResCompFrac_dCompDens; using Base::m_dWellElemCompFrac_dCompDens; + using Base::m_resPres; + using Base::m_resPhaseVolFrac; + using Base::m_dResPhaseVolFrac; + using Base::m_dResCompFrac_dCompDens; + using Base::m_resPhaseDens; + using Base::m_dResPhaseDens; + using Base::m_resPhaseVisc; + using Base::m_dResPhaseVisc; + using Base::m_resPhaseCompFrac; + using Base::m_dResPhaseCompFrac; + using Base::m_resPhaseRelPerm; + using Base::m_dResPhaseRelPerm_dPhaseVolFrac; + using Base::m_isInjector; + using Base::m_isCrossflowEnabled; /// Compile time value for the number of components static constexpr integer numComp = NC; @@ -631,6 +638,8 @@ class PerforationFluxKernel : public isothermalPerforationFluxKernels::Perforati using ThermalMultiFluidAccessors = StencilMaterialAccessors< MultiFluidBase, + fields::multifluid::phaseFraction, + fields::multifluid::dPhaseFraction, fields::multifluid::phaseEnthalpy, fields::multifluid::dPhaseEnthalpy >; @@ -645,7 +654,7 @@ class PerforationFluxKernel : public isothermalPerforationFluxKernels::Perforati using ElementViewConst = ElementRegionManager::ElementViewConst< VIEWTYPE >; PerforationFluxKernel ( PerforationData * const perforationData, - ElementSubRegionBase const & subRegion, + ElementSubRegionBase & subRegion, MultiFluidBase const & wellFluid, CompFlowAccessors const & compFlowAccessors, MultiFluidAccessors const & multiFluidAccessors, @@ -668,6 +677,8 @@ class PerforationFluxKernel : public isothermalPerforationFluxKernels::Perforati m_energyPerfFlux( perforationData->getField< fields::well::energyPerforationFlux >() ), m_dEnergyPerfFlux( perforationData->getField< fields::well::dEnergyPerforationFlux >() ), m_temp( thermalCompFlowAccessors.get( fields::flow::temperature {} ) ), + m_resPhaseFraction( thermalMultiFluidAccessors.get( fields::multifluid::phaseFraction {} ) ), + m_dResPhaseFraction( thermalMultiFluidAccessors.get( fields::multifluid::dPhaseFraction {} )), m_resPhaseEnthalpy( thermalMultiFluidAccessors.get( fields::multifluid::phaseEnthalpy {} ) ), m_dResPhaseEnthalpy( thermalMultiFluidAccessors.get( fields::multifluid::dPhaseEnthalpy {} ) ) {} @@ -690,41 +701,125 @@ class PerforationFluxKernel : public isothermalPerforationFluxKernels::Perforati } } - Base::computeFlux ( iperf, [&]( localIndex const iwelem, localIndex const er, localIndex const esr, localIndex const ei, localIndex const ip, - real64 const potDiff, real64 const flux, real64 const (&dFlux)[2][CP_Deriv::nDer] ) + Base::computeFlux ( iperf, [&]( localIndex const iwelem, localIndex const er, localIndex const esr, localIndex const ei + , real64 const potDiff, real64 const dPotDiff[2][CP_Deriv::nDer], + real64 const flux, real64 const (&dFlux)[2][CP_Deriv::nDer] ) { + real64 dMob[CP_Deriv::nDer]{}; + GEOS_UNUSED_VAR( iwelem ); if( potDiff >= 0 ) // ** reservoir cell is upstream ** { + real64 eflux = 0.0; + // loop over phases, compute and upwind phase flux + // and sum contributions to each component's perforation rate + for( integer ip = 0; ip < NP; ++ip ) + { + // skip the rest of the calculation if the phase is absent + // or if crossflow is disabled for injectors + real64 const resPhaseVolFrac = m_resPhaseVolFrac[er][esr][ei][ip]; + bool const phaseExists = (resPhaseVolFrac > 0 ); + if( !phaseExists || (m_isInjector && !m_isCrossflowEnabled) ) + { + continue; + } + + // here, we have to recompute the reservoir phase mobility (not including density) + + // density + real64 const resDens = m_resPhaseDens[er][esr][ei][0][ip]; + real64 dDens[CP_Deriv::nDer]{}; + dDens[CP_Deriv::dP] = m_dResPhaseDens[er][esr][ei][0][ip][Deriv::dP]; + dDens[CP_Deriv::dT] = m_dResPhaseDens[er][esr][ei][0][ip][Deriv::dT]; + applyChainRule( NC, m_dResCompFrac_dCompDens[er][esr][ei], + m_dResPhaseDens[er][esr][ei][0][ip], + &dDens[CP_Deriv::dC], + Deriv::dC ); + // viscosity + real64 const resVisc = m_resPhaseVisc[er][esr][ei][0][ip]; + real64 dVisc[CP_Deriv::nDer]{}; + dVisc[CP_Deriv::dP] = m_dResPhaseVisc[er][esr][ei][0][ip][Deriv::dP]; + dVisc[CP_Deriv::dT] = m_dResPhaseVisc[er][esr][ei][0][ip][Deriv::dT]; + applyChainRule( NC, m_dResCompFrac_dCompDens[er][esr][ei], + m_dResPhaseVisc[er][esr][ei][0][ip], + &dVisc[CP_Deriv::dC], + Deriv::dC ); + // enthalpy + real64 const resEnthalpy = m_resPhaseEnthalpy[er][esr][ei][0][ip]; + real64 dResEnthalpy[CP_Deriv::nDer]{}; + dResEnthalpy[CP_Deriv::dP] = m_dResPhaseEnthalpy[er][esr][ei][0][ip][Deriv::dP]; + dResEnthalpy[CP_Deriv::dT] = m_dResPhaseEnthalpy[er][esr][ei][0][ip][Deriv::dT]; + + applyChainRule( NC, m_dResCompFrac_dCompDens[er][esr][ei], + m_dResPhaseEnthalpy[er][esr][ei][0][ip], + &dResEnthalpy[CP_Deriv::dC], + Deriv::dC ); - real64 const res_enthalpy = m_resPhaseEnthalpy[er][esr][ei][0][ip]; + // relative permeability + real64 const resRelPerm = m_resPhaseRelPerm[er][esr][ei][0][ip]; + real64 dRelPerm[CP_Deriv::nDer]{}; + for( integer jc = 0; jc < CP_Deriv::nDer; ++jc ) + { + dRelPerm[jc]=0; + } + for( integer jp = 0; jp < NP; ++jp ) + { + real64 const dResRelPerm_dS = m_dResPhaseRelPerm_dPhaseVolFrac[er][esr][ei][0][ip][jp]; + dRelPerm[CP_Deriv::dP] += dResRelPerm_dS * m_dResPhaseVolFrac[er][esr][ei][jp][Deriv::dP]; + dRelPerm[CP_Deriv::dT] += dResRelPerm_dS * m_dResPhaseVolFrac[er][esr][ei][jp][Deriv::dT]; + for( integer jc = 0; jc < NC; ++jc ) + { + dRelPerm[CP_Deriv::dC+jc] += dResRelPerm_dS * m_dResPhaseVolFrac[er][esr][ei][jp][Deriv::dC+jc]; + } + } - m_energyPerfFlux[iperf] += flux * res_enthalpy; + // compute the reservoir phase mobility, including phase density and enthalpy + real64 const resPhaseMob = resDens * resRelPerm / resVisc; + real64 const resPhaseMobE = resEnthalpy * resPhaseMob; - // energy equation derivatives WRT res P & T - m_dEnergyPerfFlux[iperf][TAG::RES][CP_Deriv::dP] += dFlux[TAG::RES][CP_Deriv::dP] * res_enthalpy + - flux * m_dResPhaseEnthalpy[er][esr][ei][0][ip][Deriv::dP]; - m_dEnergyPerfFlux[iperf][TAG::RES][CP_Deriv::dT] += dFlux[TAG::RES][CP_Deriv::dT] * res_enthalpy + - flux * m_dResPhaseEnthalpy[er][esr][ei][0][ip][Deriv::dT]; - // energy equation derivatives WRT well P - m_dEnergyPerfFlux[iperf][TAG::WELL][CP_Deriv::dP] += dFlux[TAG::WELL][CP_Deriv::dP] * res_enthalpy; - m_dEnergyPerfFlux[iperf][TAG::WELL][CP_Deriv::dT] += dFlux[TAG::WELL][CP_Deriv::dT] * res_enthalpy; + // Handles all dependencies + for( integer jc = 0; jc < CP_Deriv::nDer; ++jc ) + { + dMob[jc] = resPhaseMob*dResEnthalpy[jc] + + resPhaseMobE*(dRelPerm[jc]/(resRelPerm+0.000000001) + dDens[jc] / (resDens +0.000000001) - dVisc[jc]/resVisc); + } + // compute the phase flux and derivatives using upstream cell mobility + eflux = resPhaseMobE * potDiff; + real64 dEFlux[2][CP_Deriv::nDer]{}; + // Handles all dependencies + for( integer jc = 0; jc < CP_Deriv::nDer; ++jc ) + { + dEFlux[TAG::RES][jc] = dMob[jc] * potDiff + resPhaseMobE * dPotDiff[TAG::RES][jc]; + m_dEnergyPerfFlux[iperf][TAG::WELL][jc] = resPhaseMobE * dPotDiff[TAG::WELL][jc]; + } + m_energyPerfFlux[iperf] += resPhaseVolFrac * eflux; + // energy equation derivatives WRT res P & T + m_dEnergyPerfFlux[iperf][TAG::RES][CP_Deriv::dP] += dEFlux[TAG::RES][CP_Deriv::dP] * resPhaseVolFrac + + eflux * m_dResPhaseFraction[er][esr][ei][0][ip][Deriv::dP]; + m_dEnergyPerfFlux[iperf][TAG::RES][CP_Deriv::dT] += dEFlux[TAG::RES][CP_Deriv::dT] * resPhaseVolFrac + + eflux *m_dResPhaseFraction[er][esr][ei][0][ip][Deriv::dT]; + // energy equation derivatives WRT well P - //tjb + m_dEnergyPerfFlux[iperf][TAG::WELL][CP_Deriv::dP] += dFlux[TAG::WELL][CP_Deriv::dP]; + m_dEnergyPerfFlux[iperf][TAG::WELL][CP_Deriv::dT] += dFlux[TAG::WELL][CP_Deriv::dT]; + real64 dProp_dC[numComp]{}; + applyChainRule( NC, + m_dResCompFrac_dCompDens[er][esr][ei], + m_dResPhaseFraction[er][esr][ei][0][ip], + dProp_dC, + Deriv::dC ); + for( integer jc = 0; jc < NC; ++jc ) + { + real64 const resPhaseCompFrac = m_resPhaseCompFrac[er][esr][ei][0][ip][jc]; + m_dEnergyPerfFlux[iperf][TAG::RES][CP_Deriv::dC+jc] += eflux * dProp_dC[jc] + + resPhaseCompFrac * dFlux[TAG::RES][CP_Deriv::dC+jc]; + } - // energy equation derivatives WRT reservoir dens - real64 dProp_dC[numComp]{}; - applyChainRule( NC, - m_dResCompFrac_dCompDens[er][esr][ei], - m_dResPhaseEnthalpy[er][esr][ei][0][ip], - dProp_dC, - Deriv::dC ); + } // end resevoir is upstream phase loop - for( integer jc = 0; jc < NC; ++jc ) - { - m_dEnergyPerfFlux[iperf][TAG::RES][CP_Deriv::dC+jc] += flux * dProp_dC[jc]; - } } else // ** reservoir cell is downstream { + for( integer iphase = 0; iphase < NP; ++iphase ) { bool const phaseExists = m_wellElemPhaseFrac[iwelem][0][iphase] > 0.0; @@ -814,6 +909,8 @@ class PerforationFluxKernel : public isothermalPerforationFluxKernels::Perforati ElementViewConst< arrayView1d< real64 const > > const m_temp; /// Views on phase enthalpies + ElementViewConst< arrayView3d< real64 const, multifluid::USD_PHASE > > const m_resPhaseFraction; + ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_DC > > const m_dResPhaseFraction; ElementViewConst< arrayView3d< real64 const, multifluid::USD_PHASE > > const m_resPhaseEnthalpy; ElementViewConst< arrayView4d< real64 const, multifluid::USD_PHASE_DC > > const m_dResPhaseEnthalpy; @@ -846,7 +943,7 @@ class PerforationFluxKernelFactory integer const numPhases, string const flowSolverName, PerforationData * const perforationData, - ElementSubRegionBase const & subRegion, + ElementSubRegionBase & subRegion, MultiFluidBase const & fluid, ElementRegionManager const & elemManager, bool const isInjector, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp index a949203843a..2dcde8cfe90 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp @@ -82,7 +82,7 @@ class TotalMassDensityKernel : public compositionalMultiphaseWellKernels::TotalM arraySlice2d< real64 const, multifluid::USD_PHASE_DC - 2 > dPhaseMassDens = m_dPhaseMassDens[ei][0]; real64 & dTotalMassDens_dT = m_dTotalMassDens[ei][Deriv::dT]; - dTotalMassDens_dT=0.0; + // Call the base compute the compute the total mass density and derivatives return Base::compute( ei, [&]( localIndex const ip ) { @@ -181,7 +181,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() ), @@ -191,19 +190,22 @@ 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( wellControls.getMinBHPConstraint()->isConstraintActive() ) + { + m_targetBHP = wellControls.getMinBHPConstraint()->getConstraintValue( time ); + } if( m_currentControl == WellControls::Control::PHASEVOLRATE ) { m_targetPhaseIndex = wellControls.getConstraintPhaseIndex(); + m_constraintValue = wellControls.getProdRateConstraints()[0]->getConstraintValue( time ); } } else { m_targetBHP = wellControls.getMaxBHPConstraint()->getConstraintValue( time ); - if( m_currentControl == WellControls::Control::PHASEVOLRATE ) - { - m_targetPhaseIndex = wellControls.getConstraintPhaseIndex(); - } + m_targetPhaseIndex = -1; + m_constraintValue = wellControls.getInjRateConstraints()[0]->getConstraintValue( time ); + } } @@ -372,7 +374,7 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa /// Controls WellControls::Control const m_currentControl; - real64 const m_constraintValue; + real64 m_constraintValue; real64 m_targetBHP; @@ -574,6 +576,14 @@ class ElementBasedAssemblyKernel : public compositionalMultiphaseWellKernels::El + phaseAmount * dPhaseInternalEnergy[ip][Deriv::dP]; real64 const dPhaseEnergy_dT = dPhaseAmount[FLUID_PROP_COFFSET::dT] * phaseInternalEnergy[ip] + phaseAmount * dPhaseInternalEnergy[ip][Deriv::dT]; + if( false && ei== 75 ) + { + std::cout << "taccum dp" < & dofColIndices ) { + GEOS_UNUSED_VAR( dofColIndices ); // tjb iso // No energy equation if top element and Injector // Top element defined by global index == 0 // Assumption is global index == 0 is top segment with fixed temp BC @@ -939,8 +940,9 @@ class ThermalCompositionalMultiPhaseWellFluxKernel : public IsothermalCompositio stackArray2d< real64, resNumDOF > localPerfJacobian( 1, resNumDOF ); // populate local flux vector and derivatives - real64 localPerf = -m_dt * m_energyPerfFlux[iperf]; + real64 localPerf = -m_dt * m_energyPerfFlux[iperf]; + // std::cout << "Local perf: " << iperf << " " << localPerf << std::endl; localIndex localDofIndexPres = 0; localPerfJacobian [0][localDofIndexPres] = -m_dt * m_dEnergyPerfFlux[iperf][TAG::WELL][CP_Deriv::dP]; @@ -954,6 +956,7 @@ class ThermalCompositionalMultiPhaseWellFluxKernel : public IsothermalCompositio if( eqnRowIndices >= 0 && eqnRowIndices < m_localMatrix.numRows() ) { + // tjb iso m_localMatrix.template addToRowBinarySearchUnsorted< parallelDeviceAtomic >( eqnRowIndices, dofColIndices.data(), localPerfJacobian[0].dataIfContiguous(), diff --git a/src/coreComponents/schema/schema.xsd b/src/coreComponents/schema/schema.xsd index c9b84e61719..6d2ebac39dc 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 - - - - - - - - - - - - @@ -3370,8 +3334,6 @@ When set to 2 also output convergence information to a csv--> - - @@ -3405,6 +3367,8 @@ Information output from lower logLevels is added with the desired log level + + @@ -3413,6 +3377,8 @@ Information output from lower logLevels is added with the desired log level + + @@ -3420,61 +3386,29 @@ When set to 2 also output convergence information to a csv--> - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -3486,11 +3420,6 @@ See note on referenceReservoirRegion for reservoir condition options--> - - - - - @@ -3885,7 +3814,7 @@ Information output from lower logLevels is added with the desired log level - + @@ -3913,7 +3842,7 @@ When set to 2 also output convergence information to a csv--> - + @@ -5165,8 +5094,6 @@ When set to 2 also output convergence information to a csv--> - - @@ -5188,12 +5115,16 @@ 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..9d047f8a99e 100644 --- a/src/coreComponents/schema/schema.xsd.other +++ b/src/coreComponents/schema/schema.xsd.other @@ -341,15 +341,11 @@ - - - - @@ -516,7 +512,7 @@ - + @@ -1502,7 +1498,7 @@ - + @@ -3275,7 +3271,7 @@ - + @@ -3303,7 +3299,7 @@ - + @@ -3322,11 +3318,11 @@ - + - + @@ -3336,7 +3332,7 @@ - + @@ -3346,11 +3342,11 @@ - + - + @@ -3360,7 +3356,7 @@ - + @@ -3370,7 +3366,7 @@ - + @@ -3380,7 +3376,7 @@ - + @@ -3404,7 +3400,7 @@ - + @@ -3422,7 +3418,7 @@ - + @@ -3434,7 +3430,7 @@ - + @@ -3446,7 +3442,7 @@ - + @@ -3454,11 +3450,11 @@ - + - + @@ -3481,7 +3477,7 @@ - + @@ -3507,7 +3503,7 @@ - + @@ -3528,7 +3524,7 @@ - + @@ -3558,7 +3554,7 @@ - + @@ -3572,7 +3568,7 @@ - + @@ -3603,7 +3599,7 @@ - + @@ -3648,7 +3644,7 @@ - + diff --git a/src/main/main.cpp b/src/main/main.cpp index 4673f2e228a..464e15a0497 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -23,12 +23,48 @@ #include "mainInterface/GeosxState.hpp" #include "mainInterface/version.hpp" +#include +#include // for signal() +#include using namespace geos; +static void +fpe_signal_handler( int sig, siginfo_t *sip, void *scp ) +{ + GEOS_UNUSED_VAR( sig ); + GEOS_UNUSED_VAR( scp ); + int fe_code = sip->si_code; + + printf( "In signal handler : " ); + + if( fe_code == ILL_ILLTRP ) + printf( "Illegal trap detected\n" ); + else + printf( "Code detected : %d\n", fe_code ); + + abort(); +} + +void enable_floating_point_exceptions() +{ + fenv_t env; + fegetenv( &env ); + + env.__fpcr = env.__fpcr | __fpcr_trap_invalid; + fesetenv( &env ); + + struct sigaction act; + act.sa_sigaction = fpe_signal_handler; + sigemptyset ( &act.sa_mask ); + act.sa_flags = SA_SIGINFO; + sigaction( SIGILL, &act, NULL ); +} +using namespace geos; int main( int argc, char *argv[] ) { + enable_floating_point_exceptions(); try { std::chrono::system_clock::time_point startTime = std::chrono::system_clock::now(); From a8a4654fd98da35ca93fc05714500ebbaf06f121 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Sun, 2 Nov 2025 11:31:36 -0800 Subject: [PATCH 33/41] 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 34/41] 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 35/41] 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 36/41] 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 37/41] 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 38/41] 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 7ed7b8fe695cae255b29f6479ccd9fe56e3ae607 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Mon, 3 Nov 2025 10:42:18 -0800 Subject: [PATCH 39/41] thermal test case prod runs ~25yrs, inj ~1yr --- .../wells/CompositionalMultiphaseWell.cpp | 112 ++++++++++++------ .../fluidFlow/wells/WellControls.cpp | 11 +- .../fluidFlow/wells/WellControls.hpp | 26 +++- .../fluidFlow/wells/WellPropWriter.hpp | 26 +++- .../fluidFlow/wells/WellSolverBase.cpp | 21 ++-- .../CompositionalMultiphaseWellKernels.cpp | 1 - .../CompositionalMultiphaseWellKernels.hpp | 28 +++-- .../wells/kernels/PerforationFluxKernels.hpp | 6 +- ...rmalCompositionalMultiphaseWellKernels.hpp | 10 +- ...mpositionalMultiphaseReservoirAndWells.cpp | 1 + .../CoupledReservoirAndWellKernels.hpp | 21 +++- 11 files changed, 186 insertions(+), 77 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index ed9269bc5a7..08ff6d22856 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -498,7 +498,7 @@ void CompositionalMultiphaseWell::outputWellDebug( real64 const time, WellElementSubRegion & subRegion ) { - if( m_writeSegDebug > 0 ) + if( m_writeSegDebug > 1 ) { CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); auto solver_names = getParent().getSubGroupsNames(); @@ -620,13 +620,13 @@ void CompositionalMultiphaseWell::outputWellDebug( real64 const time, if( isThermal() ) { m_wellPropWriter[srn].registerPerfResProp( "Temperature", compFlowAccessors.get( fields::flow::temperature{} )); - m_wellPropWriter[srn].registerPerfResPhasePropf( "Enthalpy", multiFluidAccessors.get( fields::multifluid::phaseEnthalpy{} )); - m_wellPropWriter[srn].registerPerfResPhasePropf( "InternalEnergy", multiFluidAccessors.get( fields::multifluid::phaseInternalEnergy{} )); + m_wellPropWriter[srn].registerPerfResPhasePropf( "PhaseEnthalpy", multiFluidAccessors.get( fields::multifluid::phaseEnthalpy{} )); + m_wellPropWriter[srn].registerPerfResPhasePropf( "PhaseInternalEnergy", multiFluidAccessors.get( fields::multifluid::phaseInternalEnergy{} )); } m_wellPropWriter[srn].registerPerfComponentProp( "CompPerfRate", perforationData.getField< fields::well::compPerforationRate >()); - m_wellPropWriter[srn].registerPerfResComponentProp( "ComponentDensity", compFlowAccessors.get( fields::flow::globalCompDensity{} )); - m_wellPropWriter[srn].registerPerfResPhaseComponentProp( "PhaseCompFrac", multiFluidAccessors.get( fields::multifluid::phaseCompFraction{} )); - m_wellPropWriter[srn].registerPerfResPhaseProp( "PhaseVolFrac", compFlowAccessors.get( fields::flow::phaseVolumeFraction{} )); + // m_wellPropWriter[srn].registerPerfResComponentProp( "ComponentDensity", compFlowAccessors.get( fields::flow::globalCompDensity{} )); + m_wellPropWriter[srn].registerPerfResPhaseComponentProp( "PhaseCompFrac", multiFluidAccessors.get( fields::multifluid::phaseCompFraction{} )); + m_wellPropWriter[srn].registerPerfResPhaseProp( "PhaseVolFrac", compFlowAccessors.get( fields::flow::phaseVolumeFraction{} )); m_wellPropWriter[srn].registerPerfResPhasePropf( "Viscosity", multiFluidAccessors.get( fields::multifluid::phaseViscosity{} )); m_wellPropWriter[srn].registerPerfResPhasePropf( "RelPerm", relPermAccessors.get( fields::relperm::phaseRelPerm{} )); @@ -657,7 +657,7 @@ void CompositionalMultiphaseWell::outputSingleWellDebug( real64 const time, GEOS_UNUSED_VAR( localRhs ); - if( m_writeSegDebug > 0 ) + if( m_writeSegDebug > 1 ) { CompositionalMultiphaseBase const & flowSolver = getParent().getGroup< CompositionalMultiphaseBase >( getFlowSolverName() ); auto solver_names = getParent().getSubGroupsNames(); @@ -780,11 +780,11 @@ void CompositionalMultiphaseWell::outputSingleWellDebug( real64 const time, if( isThermal() ) { m_wellPropWriter[srn].registerPerfResProp( "Temperature", compFlowAccessors.get( fields::flow::temperature{} )); - m_wellPropWriter[srn].registerPerfResPhasePropf( "Enthalpy", multiFluidAccessors.get( fields::multifluid::phaseEnthalpy{} )); - m_wellPropWriter[srn].registerPerfResPhasePropf( "InternalEnergy", multiFluidAccessors.get( fields::multifluid::phaseInternalEnergy{} )); + m_wellPropWriter[srn].registerPerfResPhasePropf( "PhaseEnthalpy", multiFluidAccessors.get( fields::multifluid::phaseEnthalpy{} )); + m_wellPropWriter[srn].registerPerfResPhasePropf( "PhaseInternalEnergy", multiFluidAccessors.get( fields::multifluid::phaseInternalEnergy{} )); } m_wellPropWriter[srn].registerPerfComponentProp( "CompPerfRate", perforationData.getField< fields::well::compPerforationRate >()); - m_wellPropWriter[srn].registerPerfResComponentProp( "ComponentDensity", compFlowAccessors.get( fields::flow::globalCompDensity{} )); + //m_wellPropWriter[srn].registerPerfResComponentProp( "ComponentDensity", compFlowAccessors.get( fields::flow::globalCompDensity{} )); m_wellPropWriter[srn].registerPerfResPhaseComponentProp( "PhaseCompFrac", multiFluidAccessors.get( fields::multifluid::phaseCompFraction{} )); m_wellPropWriter[srn].registerPerfResPhaseProp( "PhaseVolFrac", compFlowAccessors.get( fields::flow::phaseVolumeFraction{} )); m_wellPropWriter[srn].registerPerfResPhasePropf( "Viscosity", multiFluidAccessors.get( fields::multifluid::phaseViscosity{} )); @@ -936,10 +936,11 @@ void CompositionalMultiphaseWell::printSegRates( real64 const & time, if( isThermal() ) { m_wellPropWriter_eot[srn].registerPerfResProp( "Temperature", compFlowAccessors.get( fields::flow::temperature{} )); - m_wellPropWriter[srn].registerPerfResPhaseProp( "Enthalpy", multiFluidAccessors.get( fields::multifluid::phaseEnthalpy{} )); + m_wellPropWriter_eot[srn].registerPerfResPhasePropf( "PhaseEnthalpy", multiFluidAccessors.get( fields::multifluid::phaseEnthalpy{} )); + m_wellPropWriter_eot[srn].registerPerfResPhasePropf( "PhaseInternalEnergy", multiFluidAccessors.get( fields::multifluid::phaseInternalEnergy{} )); } m_wellPropWriter_eot[srn].registerPerfComponentProp( "CompPerfRate", perforationData.getField< fields::well::compPerforationRate >()); - m_wellPropWriter_eot[srn].registerPerfResComponentProp( "ComponentDensity", compFlowAccessors.get( fields::flow::globalCompDensity{} )); + //m_wellPropWriter_eot[srn].registerPerfResComponentProp( "ComponentDensity", compFlowAccessors.get( fields::flow::globalCompDensity{} )); m_wellPropWriter_eot[srn].registerPerfResPhaseComponentProp( "PhaseCompFrac", multiFluidAccessors.get( fields::multifluid::phaseCompFraction{} )); m_wellPropWriter_eot[srn].registerPerfResPhaseProp( "PhaseVolFrac", compFlowAccessors.get( fields::flow::phaseVolumeFraction{} )); m_wellPropWriter_eot[srn].registerPerfResPhasePropf( "Viscosity", multiFluidAccessors.get( fields::multifluid::phaseViscosity{} )); @@ -1720,6 +1721,32 @@ 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 ); + } + } ); + } + } } } @@ -1906,6 +1933,7 @@ void CompositionalMultiphaseWell::assembleWellAccumulationTerms( real64 const & ElementBasedAssemblyKernelFactory:: createAndLaunch< parallelDevicePolicy<> >( numComponents, numPhases, + wellControls, wellControls.isProducer(), dofManager.rankOffset(), kernelFlags, @@ -1921,6 +1949,7 @@ void CompositionalMultiphaseWell::assembleWellAccumulationTerms( real64 const & ElementBasedAssemblyKernelFactory:: createAndLaunch< parallelDevicePolicy<> >( numComponents, numPhases, + wellControls, wellControls.isProducer(), dofManager.rankOffset(), kernelFlags, @@ -2050,6 +2079,7 @@ CompositionalMultiphaseWell::applyWellBoundaryConditions( real64 const time_n, coupledReservoirAndWellKernels:: ThermalCompositionalMultiPhaseWellFluxKernelFactory:: createAndLaunch< parallelDevicePolicy<> >( numComps, + wellControls, wellControls.isProducer(), dt, rankOffset, @@ -2829,15 +2859,11 @@ 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 const & wellElemTemperature = subRegion.getField< well::temperature >(); @@ -3050,15 +3072,11 @@ void CompositionalMultiphaseWell::chopNegativeDensities( DomainPartition & domai } } } ); - return; - if( isThermal() ) + WellControls const & wellControls = getWellControls( subRegion ); + if( isThermal() && !wellControls.isInjector() ) { - WellControls const & wellControls = getWellControls( subRegion ); - real64 minTemp; - if( wellControls.isInjector() ) - minTemp = wellControls.getInjectionTemperature(); - else - minTemp=280.0; + + real64 minTemp =290.0; arrayView1d< real64 > const & wellElemTemperature = subRegion.getField< well::temperature >(); @@ -3427,6 +3445,8 @@ void CompositionalMultiphaseWell::implicitStepComplete( real64 const & time_n, if( getLogLevel() > 0 ) { printRates( time_n, dt, domain ); + auto iterInfo = currentIter( time_n, dt ); + printSegRates( time_n, dt, std::get< 0 >( iterInfo ), std::get< 1 >( iterInfo ), std::get< 2 >( iterInfo ), domain ); } } @@ -3612,10 +3632,11 @@ bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, { constraintList.push_back( wellControls.getMinBHPConstraint() ); } + constraintList.insert( constraintList.begin(), limitingConstraint ); } } // Solve minimum bhp constraint first - if( wellControls.getMinBHPConstraint()->isConstraintActive() ) + if( false && wellControls.getMinBHPConstraint()->isConstraintActive() ) { // this is related to WHP option which introduces a new BHP constraint limitingConstraint = wellControls.getMinBHPConstraint(); @@ -3632,16 +3653,29 @@ bool CompositionalMultiphaseWell::evaluateConstraints( real64 const & time_n, { if( limitingConstraint->getControl() != ConstraintTypeId::BHP ) { // remove from list and add BHP constraint - auto it = std::find( constraintList.begin(), constraintList.end(), limitingConstraint ); - if( it != constraintList.end() ) - { - constraintList.erase( it ); - } + //auto it = std::find( constraintList.begin(), constraintList.end(), limitingConstraint ); + //if( it != constraintList.end() ) + //{ + // constraintList.erase( it ); + //} constraintList.push_back( wellControls.getMaxBHPConstraint() ); } } } - + if( wellControls.isoThermalEstimatorEnabled() ) + { + wellControls.enableThermalEffects( false ); + solveConstraint ( limitingConstraint, time_n, + dt, + cycleNumber, + coupledIterationNumber, + domain, + mesh, + elemManager, + subRegion, + dofManager ); + wellControls.enableThermalEffects( true ); + } solveConstraint ( limitingConstraint, time_n, dt, cycleNumber, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index 754a528d0ad..2424621dfd6 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -44,7 +44,8 @@ WellControls::WellControls( string const & name, Group * const parent ) m_estimateSolution( false ), m_currentConstraint( nullptr ), m_wellStatus( WellControls::Status::OPEN ), - m_regionAveragePressure( -1 ) + m_regionAveragePressure( -1 ), + m_enableIsoThermalEstimator( 0 ) { setInputFlags( InputFlags::OPTIONAL_NONUNIQUE ); @@ -103,6 +104,14 @@ WellControls::WellControls( string const & name, Group * const parent ) setInputFlag( InputFlags::OPTIONAL ). setDescription( "Flag to esitmate well solution prior to coupled reservoir and well solve." ); + registerWrapper( viewKeyStruct::enableIsoThermalEstimatorString(), &m_enableIsoThermalEstimator ). + setDefaultValue( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Estimator configuration option to disable thermal effects on initial well constraint solve and then converge solution with thermal effects enabled: \n" + " - If the flag is set to 1, thermal effects are enabled during the initial constraint solve. \n" + " - If the flag is set to 0, thermal effects are disabled during the initial constraint solve." ); + + addLogLevel< logInfo::WellControl >(); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp index a44f3a15350..44a20ba265d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.hpp @@ -445,6 +445,27 @@ class WellControls : public dataRepository::Group WellControls::Status getWellStatus () const { return m_wellStatus; } ///@} + /** + * @brief Set thermal effects enable + * @param[in] true/false + */ + void enableThermalEffects ( bool enable ) { m_thermalEffectsEnabled = enable; }; + + /** + * @brief Are thermal effects enabled + * @return true if thermal effects are enabled, false otherwise + */ + bool thermalEffectsEnabled() const { return m_thermalEffectsEnabled; } + + /** + * @brief Is isoThermalEstimator enabled + * @return true if isoThermalEstimator is enabled, false otherwise + */ + bool isoThermalEstimatorEnabled() const { return m_enableIsoThermalEstimator; } + + + ///@} + /** * @brief Struct to serve as a container for variable strings and keys. * @struct viewKeyStruct @@ -478,7 +499,8 @@ class WellControls : public dataRepository::Group 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 enable iso thermal estimator flag + static constexpr char const * enableIsoThermalEstimatorString() { return "enableIsoThermalEstimator"; } /// 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 @@ -606,6 +628,8 @@ class WellControls : public dataRepository::Group /// Region average temperature used in volume rate constraint calculations real64 m_regionAverageTemperature; + bool m_thermalEffectsEnabled; + integer m_enableIsoThermalEstimator; }; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPropWriter.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPropWriter.hpp index cf0e4ae59b9..c9accc4f717 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPropWriter.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPropWriter.hpp @@ -145,12 +145,12 @@ class WellPropWriter stream << "," << m_prop[er][esr][ei][0][i]; } }; - template< typename T > struct typed_2d_perf_res_prop_writer : public perf_prop_writer + template< typename T > struct typed_2d_perf_res_phase_prop_writer : public perf_prop_writer { typedef T value_type; typedef typed_prop_wrapper< value_type > prop_wrapper_type; - typed_2d_perf_res_prop_writer( value_type & prop, integer dim2 ): m_prop( prop ), m_Dim2( dim2 ){} + typed_2d_perf_res_phase_prop_writer( value_type & prop, integer dim2 ): m_prop( prop ), m_Dim2( dim2 ){} value_type const m_prop; const integer m_Dim2; @@ -160,6 +160,25 @@ class WellPropWriter for( integer i=0; i struct typed_2d_perf_res_prop_writer : public perf_prop_writer + { + typedef T value_type; + typedef typed_prop_wrapper< value_type > prop_wrapper_type; + + typed_2d_perf_res_prop_writer( value_type & prop, integer dim2 ): m_prop( prop ), m_Dim2( dim2 ){} + value_type const m_prop; + const integer m_Dim2; + + virtual void write_prop( const integer g, const integer er, const integer esr, const integer ei, std::ofstream & stream ) + { + GEOS_UNUSED_VAR( g ); + GEOS_UNUSED_VAR( er ); + GEOS_UNUSED_VAR( esr ); + for( integer i=0; i struct typed_2d_prop_writer : public prop_writer { @@ -379,6 +398,7 @@ class WellPropWriter } m_perfPropWriterVec.push_back( new typed_2d_perf_res_prop_writer( prop, m_numComponent )); } + template< typename T > void registerPerfResPhaseComponentProp( std::string const & name, const T & prop ) { @@ -446,7 +466,7 @@ class WellPropWriter m_perfHeader.push_back( name+"_"+p ); } - m_perfPropWriterVec.push_back( new typed_2d_perf_res_prop_writer( prop, m_numPhase )); + m_perfPropWriterVec.push_back( new typed_2d_perf_res_phase_prop_writer( prop, m_numPhase )); } template< typename T > void registerPerfResPhasePropf( std::string const & name, const T & prop ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp index 6cdcc152374..9c71ab571f0 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp @@ -116,8 +116,7 @@ void WellSolverBase::postInputInitialization() // 1. Set key dimensions of the problem m_numDofPerWellElement = m_isThermal ? m_numComponents + 2 : m_numComponents + 1; // 1 pressure connectionRate + temp if thermal m_numDofPerResElement = m_isThermal ? m_numComponents + 1: m_numComponents; // 1 pressure + temp if thermal - - + m_writeSegDebug=2; if( m_writeSegDebug > 0 ) { if( m_writeCSV == 0 ) @@ -508,14 +507,12 @@ void WellSolverBase::assembleWellSystem( real64 const time_n, computeWellPerforationRates( time_n, dt, elementRegionManager, subRegion ); assembleWellFluxTerms( time_n, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); my_ctime=my_ctime+1; - /* - if ( !m_useNewCode ) - { - auto iterInfo = currentIter( time_n, dt ); - outputWellDebug( time_n, dt, std::get< 0 >( iterInfo ), std::get< 1 >( iterInfo ), std::get< 2 >( iterInfo ), - domain, dofManager, localMatrix, localRhs ); - } - */ + + // auto iterInfo = currentIter( time_n, dt ); + // outputWellDebug( time_n, dt, std::get< 0 >( iterInfo ), std::get< 1 >( iterInfo ), std::get< 2 >( iterInfo ), + // domain, dofManager, localMatrix, localRhs ); + + } void WellSolverBase::assembleSystem( real64 const time, @@ -787,7 +784,7 @@ bool WellSolverBase::solveNonlinearSystem( real64 const & time_n, { if( m_nonlinearSolverParameters.getLogLevel() > 4 ) GEOS_LOG_LEVEL_RANK_0( logInfo::NonlinearSolver, - GEOS_FMT( " Well: {} Est Attempt: {:2}, ConfigurationIter: {:2}, NewtonIter: {:2}", subRegion.getName(), dtAttempt, configurationLoopIter, newtonIter )); + GEOS_FMT( " Well: {} Est Attempt: NewtonIter: {:2}", subRegion.getName(), stepDt, newtonIter )); { Timer timer( m_timers["assemble"] ); @@ -1000,9 +997,7 @@ bool WellSolverBase::solveNonlinearSystem( real64 const & time_n, } lastResidual = residualNorm; - std::cout << "lastResidual " << lastResidual << std::endl; } - std::cout << "isNewtonConverged " << isNewtonConverged << std::endl; return isNewtonConverged; } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp index 57349d508a9..83d0f3e9802 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp @@ -723,7 +723,6 @@ RateInitializationKernel:: { forAll< parallelDevicePolicy<> >( subRegionSize, [=] GEOS_HOST_DEVICE ( localIndex const iwelem ) { - std::cout << "rate est " << iwelem << " " << constraintVal << std::endl; connRate[iwelem] = constraintVal * totalDens[iwelem][0]; } ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp index 9a1506b306f..5569d94a7f3 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.hpp @@ -540,7 +540,7 @@ class ResidualNormKernel : public physicsSolverBaseKernels::ResidualNormKernelBa { m_targetBHP = wellControls.getMaxBHPConstraint()->getConstraintValue( time ); - // tjb Note this assumes that there is only one rate constraint + // tjbNote 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) @@ -845,6 +845,7 @@ class ElementBasedAssemblyKernel * @param[inout] localRhs the local right-hand side vector */ ElementBasedAssemblyKernel( localIndex const numPhases, + bool const thermalEffectsEnabled, integer const isProducer, globalIndex const rankOffset, string const dofKey, @@ -854,6 +855,7 @@ class ElementBasedAssemblyKernel arrayView1d< real64 > const & localRhs, BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > const kernelFlags ) : m_numPhases( numPhases ), + m_thermalEffectsEnabled( thermalEffectsEnabled ), m_isProducer( isProducer ), m_rankOffset( rankOffset ), m_iwelemControl( subRegion.getTopWellElementIndex() ), @@ -1135,12 +1137,8 @@ class ElementBasedAssemblyKernel if constexpr ( IS_THERMAL) { - if( ei == m_iwelemControl && !m_isProducer ) + if( !m_thermalEffectsEnabled ) { - // For top segment energy balance eqn replaced with T(n+1) - T = 0 - // No other energy balance derivatives - // Assumption is global index == 0 is top segment with fixed temp BC - for( integer i=0; i < numComp+1+IS_THERMAL; i++ ) { stack.localJacobian[numRows-1][i] = 0.0; @@ -1152,8 +1150,12 @@ class ElementBasedAssemblyKernel stack.localResidual[numRows-1]=0.0; } - } - /* tjb iso + else if( ei == m_iwelemControl && !m_isProducer ) + { + // For top segment energy balance eqn replaced with T(n+1) - T = 0 + // No other energy balance derivatives + // Assumption is global index == 0 is top segment with fixed temp BC + for( integer i=0; i < numComp+1+IS_THERMAL; i++ ) { stack.localJacobian[numRows-1][i] = 0.0; @@ -1164,7 +1166,10 @@ class ElementBasedAssemblyKernel stack.localJacobian[numRows-1][numRows-1] = 1.0; stack.localResidual[numRows-1]=0.0; - */ + } + + + } if( m_kernelFlags.isSet( isothermalCompositionalMultiphaseBaseKernels::KernelFlags::TotalMassEquation ) ) { // apply equation/variable change transformation to the component mass balance equations @@ -1223,6 +1228,8 @@ class ElementBasedAssemblyKernel /// Number of fluid phases integer const m_numPhases; + /// Flag indicating whether thermal effects are enabled + bool const m_thermalEffectsEnabled; /// Well type integer const m_isProducer; @@ -1302,6 +1309,7 @@ class ElementBasedAssemblyKernelFactory static void createAndLaunch( localIndex const numComps, localIndex const numPhases, + WellControls const & wellControls, integer const isProducer, globalIndex const rankOffset, BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags, @@ -1318,7 +1326,7 @@ class ElementBasedAssemblyKernelFactory integer constexpr istherm = IS_THERMAL(); ElementBasedAssemblyKernel< NUM_COMP, istherm > - kernel( numPhases, isProducer, rankOffset, dofKey, subRegion, fluid, localMatrix, localRhs, kernelFlags ); + kernel( numPhases, wellControls.thermalEffectsEnabled(), isProducer, rankOffset, dofKey, subRegion, fluid, localMatrix, localRhs, kernelFlags ); ElementBasedAssemblyKernel< NUM_COMP, istherm >::template launch< POLICY, ElementBasedAssemblyKernel< NUM_COMP, istherm > >( subRegion.size(), kernel ); } ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/PerforationFluxKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/PerforationFluxKernels.hpp index d618272de94..e69615be8b9 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/PerforationFluxKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/PerforationFluxKernels.hpp @@ -780,7 +780,7 @@ class PerforationFluxKernel : public isothermalPerforationFluxKernels::Perforati for( integer jc = 0; jc < CP_Deriv::nDer; ++jc ) { dMob[jc] = resPhaseMob*dResEnthalpy[jc] + - resPhaseMobE*(dRelPerm[jc]/(resRelPerm+0.000000001) + dDens[jc] / (resDens +0.000000001) - dVisc[jc]/resVisc); + resPhaseMobE*(dRelPerm[jc]/(resRelPerm+0.000000001) + dDens[jc] / (resDens +0.000000001) - dVisc[jc]/(resVisc+0.000000001)); } // compute the phase flux and derivatives using upstream cell mobility eflux = resPhaseMobE * potDiff; @@ -798,8 +798,8 @@ class PerforationFluxKernel : public isothermalPerforationFluxKernels::Perforati m_dEnergyPerfFlux[iperf][TAG::RES][CP_Deriv::dT] += dEFlux[TAG::RES][CP_Deriv::dT] * resPhaseVolFrac + eflux *m_dResPhaseFraction[er][esr][ei][0][ip][Deriv::dT]; // energy equation derivatives WRT well P - //tjb - m_dEnergyPerfFlux[iperf][TAG::WELL][CP_Deriv::dP] += dFlux[TAG::WELL][CP_Deriv::dP]; - m_dEnergyPerfFlux[iperf][TAG::WELL][CP_Deriv::dT] += dFlux[TAG::WELL][CP_Deriv::dT]; + m_dEnergyPerfFlux[iperf][TAG::WELL][CP_Deriv::dP] += dEFlux[TAG::WELL][CP_Deriv::dP]; + m_dEnergyPerfFlux[iperf][TAG::WELL][CP_Deriv::dT] += dEFlux[TAG::WELL][CP_Deriv::dT]; real64 dProp_dC[numComp]{}; applyChainRule( NC, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp index 2dcde8cfe90..fe99ea6828e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/ThermalCompositionalMultiphaseWellKernels.hpp @@ -492,6 +492,7 @@ class ElementBasedAssemblyKernel : public compositionalMultiphaseWellKernels::El * @param[inout] localRhs the local right-hand side vector */ ElementBasedAssemblyKernel( localIndex const numPhases, + bool const thermalEffectsEnabled, integer const isProducer, globalIndex const rankOffset, string const dofKey, @@ -500,7 +501,7 @@ class ElementBasedAssemblyKernel : public compositionalMultiphaseWellKernels::El CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs, BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > const kernelFlags ) - : Base( numPhases, isProducer, rankOffset, dofKey, subRegion, fluid, localMatrix, localRhs, kernelFlags ), + : Base( numPhases, thermalEffectsEnabled, isProducer, rankOffset, dofKey, subRegion, fluid, localMatrix, localRhs, kernelFlags ), m_phaseInternalEnergy_n( fluid.phaseInternalEnergy_n()), m_phaseInternalEnergy( fluid.phaseInternalEnergy()), m_dPhaseInternalEnergy( fluid.dPhaseInternalEnergy()) @@ -660,6 +661,7 @@ class ElementBasedAssemblyKernelFactory static void createAndLaunch( localIndex const numComps, localIndex const numPhases, + WellControls const & wellControls, integer const isProducer, globalIndex const rankOffset, BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags, @@ -674,7 +676,7 @@ class ElementBasedAssemblyKernelFactory localIndex constexpr NUM_COMP = NC(); ElementBasedAssemblyKernel< NUM_COMP > - kernel( numPhases, isProducer, rankOffset, dofKey, subRegion, fluid, localMatrix, localRhs, kernelFlags ); + kernel( numPhases, wellControls.thermalEffectsEnabled(), isProducer, rankOffset, dofKey, subRegion, fluid, localMatrix, localRhs, kernelFlags ); ElementBasedAssemblyKernel< NUM_COMP >::template launch< POLICY, ElementBasedAssemblyKernel< NUM_COMP > >( subRegion.size(), kernel ); } ); @@ -754,6 +756,7 @@ class FaceBasedAssemblyKernel : public compositionalMultiphaseWellKernels::FaceB , localRhs , kernelFlags ), m_numPhases ( fluid.numFluidPhases()), + m_thermalEffectsEnabled( wellControls.thermalEffectsEnabled()), m_globalWellElementIndex( subRegion.getGlobalWellElementIndex() ), m_phaseFraction( fluid.phaseFraction()), m_dPhaseFraction( fluid.dPhaseFraction()), @@ -801,6 +804,7 @@ class FaceBasedAssemblyKernel : public compositionalMultiphaseWellKernels::FaceB { Base::complete ( iwelem, stack ); // tjb iso return; + if( !m_thermalEffectsEnabled ) return; using namespace compositionalMultiphaseUtilities; if( stack.numConnectedElems ==1 ) { @@ -1082,6 +1086,8 @@ class FaceBasedAssemblyKernel : public compositionalMultiphaseWellKernels::FaceB protected: /// Number of phases integer const m_numPhases; + /// Flag specifying whether thermal effects are enabled + bool const m_thermalEffectsEnabled; /// Global index of local element arrayView1d< globalIndex const > m_globalWellElementIndex; diff --git a/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp b/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp index a05210044d8..0d765e18f64 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp +++ b/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp @@ -344,6 +344,7 @@ assembleCouplingTerms( real64 const time_n, coupledReservoirAndWellKernels:: ThermalCompositionalMultiPhaseFluxKernelFactory:: createAndLaunch< parallelDevicePolicy<> >( numComps, + wellControls, wellControls.isProducer(), dt, rankOffset, diff --git a/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellKernels.hpp b/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellKernels.hpp index 36c0efaf83f..993bc89aa85 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellKernels.hpp +++ b/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellKernels.hpp @@ -639,6 +639,7 @@ class ThermalCompositionalMultiPhaseFluxKernel : public IsothermalCompositionalM * @param[in] kernelFlags flags packed together */ ThermalCompositionalMultiPhaseFluxKernel( real64 const dt, + bool const thermalEffectsEnabled, integer const isProducer, globalIndex const rankOffset, string const wellDofKey, @@ -663,6 +664,7 @@ class ThermalCompositionalMultiPhaseFluxKernel : public IsothermalCompositionalM detectCrossflow, numCrossFlowPerforations, kernelFlags ), + m_thermalEffectsEnabled( thermalEffectsEnabled ), m_isProducer( isProducer ), m_globalWellElementIndex( subRegion.getGlobalWellElementIndex() ), m_energyPerfFlux( perforationData->getField< fields::well::energyPerforationFlux >()), @@ -688,6 +690,8 @@ class ThermalCompositionalMultiPhaseFluxKernel : public IsothermalCompositionalM stackArray1d< globalIndex, 2*resNumDOF > & dofColIndices, localIndex const iwelem ) { + if( !m_thermalEffectsEnabled ) + return; // No energy equation if top element and Injector // Top element defined by global index == 0 // Assumption is global index == 0 is top segment with fixed temp BC @@ -766,6 +770,8 @@ class ThermalCompositionalMultiPhaseFluxKernel : public IsothermalCompositionalM } protected: + /// Flag specifying whether thermal effects are enabled + bool const m_thermalEffectsEnabled; /// Well type integer const m_isProducer; @@ -801,6 +807,7 @@ class ThermalCompositionalMultiPhaseFluxKernelFactory template< typename POLICY > static void createAndLaunch( integer const numComps, + WellControls const & wellControls, integer const isProducer, real64 const dt, globalIndex const rankOffset, @@ -821,7 +828,7 @@ class ThermalCompositionalMultiPhaseFluxKernelFactory integer constexpr NUM_COMP = NC(); using kernelType = ThermalCompositionalMultiPhaseFluxKernel< NUM_COMP, 1 >; - kernelType kernel( dt, isProducer, rankOffset, wellDofKey, subRegion, resDofNumber, perforationData, + kernelType kernel( dt, wellControls.thermalEffectsEnabled(), isProducer, rankOffset, wellDofKey, subRegion, resDofNumber, perforationData, fluid, localRhs, localMatrix, detectCrossflow, numCrossFlowPerforations, kernelFlags ); kernelType::template launch< POLICY >( perforationData->size(), kernel ); } ); @@ -883,6 +890,7 @@ class ThermalCompositionalMultiPhaseWellFluxKernel : public IsothermalCompositio * @param[in] kernelFlags flags packed together */ ThermalCompositionalMultiPhaseWellFluxKernel( real64 const dt, + bool const thermalEffectsEnabled, integer const isProducer, globalIndex const rankOffset, string const wellDofKey, @@ -901,6 +909,7 @@ class ThermalCompositionalMultiPhaseWellFluxKernel : public IsothermalCompositio localRhs, localMatrix, kernelFlags ), + m_thermalEffectsEnabled( thermalEffectsEnabled ), m_isProducer( isProducer ), m_globalWellElementIndex( subRegion.getGlobalWellElementIndex() ), m_energyPerfFlux( perforationData->getField< fields::well::energyPerforationFlux >()), @@ -925,7 +934,9 @@ class ThermalCompositionalMultiPhaseWellFluxKernel : public IsothermalCompositio localIndex const iwelem, stackArray1d< globalIndex, resNumDOF > & dofColIndices ) { - GEOS_UNUSED_VAR( dofColIndices ); // tjb iso + GEOS_UNUSED_VAR( dofColIndices ); + if( !m_thermalEffectsEnabled ) // tjb iso + return; // No energy equation if top element and Injector // Top element defined by global index == 0 // Assumption is global index == 0 is top segment with fixed temp BC @@ -991,7 +1002,8 @@ class ThermalCompositionalMultiPhaseWellFluxKernel : public IsothermalCompositio } protected: - + /// Thermal effects enabled + bool const m_thermalEffectsEnabled; /// Well type integer const m_isProducer; @@ -1026,6 +1038,7 @@ class ThermalCompositionalMultiPhaseWellFluxKernelFactory template< typename POLICY > static void createAndLaunch( integer const numComps, + WellControls const & wellControls, integer const isProducer, real64 const dt, globalIndex const rankOffset, @@ -1043,7 +1056,7 @@ class ThermalCompositionalMultiPhaseWellFluxKernelFactory integer constexpr NUM_COMP = NC(); using kernelType = ThermalCompositionalMultiPhaseWellFluxKernel< NUM_COMP, 1 >; - kernelType kernel( dt, isProducer, rankOffset, wellDofKey, subRegion, perforationData, + kernelType kernel( dt, wellControls.thermalEffectsEnabled(), isProducer, rankOffset, wellDofKey, subRegion, perforationData, fluid, localRhs, localMatrix, kernelFlags ); kernelType::template launch< POLICY >( perforationData->size(), kernel ); } ); From 12bbd4dc464af9a8ec29f1ffdcd52fc7e2989111 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Mon, 3 Nov 2025 10:44:09 -0800 Subject: [PATCH 40/41] uncrustify --- .../wells/CompositionalMultiphaseWell.cpp | 25 ++++++++++++------- .../fluidFlow/wells/WellPropWriter.hpp | 4 +-- .../fluidFlow/wells/WellSolverBase.cpp | 12 ++++----- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 08ff6d22856..e43f3183f10 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -624,9 +624,10 @@ void CompositionalMultiphaseWell::outputWellDebug( real64 const time, m_wellPropWriter[srn].registerPerfResPhasePropf( "PhaseInternalEnergy", multiFluidAccessors.get( fields::multifluid::phaseInternalEnergy{} )); } m_wellPropWriter[srn].registerPerfComponentProp( "CompPerfRate", perforationData.getField< fields::well::compPerforationRate >()); - // m_wellPropWriter[srn].registerPerfResComponentProp( "ComponentDensity", compFlowAccessors.get( fields::flow::globalCompDensity{} )); - m_wellPropWriter[srn].registerPerfResPhaseComponentProp( "PhaseCompFrac", multiFluidAccessors.get( fields::multifluid::phaseCompFraction{} )); - m_wellPropWriter[srn].registerPerfResPhaseProp( "PhaseVolFrac", compFlowAccessors.get( fields::flow::phaseVolumeFraction{} )); + // m_wellPropWriter[srn].registerPerfResComponentProp( "ComponentDensity", compFlowAccessors.get( + // fields::flow::globalCompDensity{} )); + m_wellPropWriter[srn].registerPerfResPhaseComponentProp( "PhaseCompFrac", multiFluidAccessors.get( fields::multifluid::phaseCompFraction{} )); + m_wellPropWriter[srn].registerPerfResPhaseProp( "PhaseVolFrac", compFlowAccessors.get( fields::flow::phaseVolumeFraction{} )); m_wellPropWriter[srn].registerPerfResPhasePropf( "Viscosity", multiFluidAccessors.get( fields::multifluid::phaseViscosity{} )); m_wellPropWriter[srn].registerPerfResPhasePropf( "RelPerm", relPermAccessors.get( fields::relperm::phaseRelPerm{} )); @@ -940,7 +941,8 @@ void CompositionalMultiphaseWell::printSegRates( real64 const & time, m_wellPropWriter_eot[srn].registerPerfResPhasePropf( "PhaseInternalEnergy", multiFluidAccessors.get( fields::multifluid::phaseInternalEnergy{} )); } m_wellPropWriter_eot[srn].registerPerfComponentProp( "CompPerfRate", perforationData.getField< fields::well::compPerforationRate >()); - //m_wellPropWriter_eot[srn].registerPerfResComponentProp( "ComponentDensity", compFlowAccessors.get( fields::flow::globalCompDensity{} )); + //m_wellPropWriter_eot[srn].registerPerfResComponentProp( "ComponentDensity", compFlowAccessors.get( + // fields::flow::globalCompDensity{} )); m_wellPropWriter_eot[srn].registerPerfResPhaseComponentProp( "PhaseCompFrac", multiFluidAccessors.get( fields::multifluid::phaseCompFraction{} )); m_wellPropWriter_eot[srn].registerPerfResPhaseProp( "PhaseVolFrac", compFlowAccessors.get( fields::flow::phaseVolumeFraction{} )); m_wellPropWriter_eot[srn].registerPerfResPhasePropf( "Viscosity", multiFluidAccessors.get( fields::multifluid::phaseViscosity{} )); @@ -1727,10 +1729,12 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh updateSubRegionState( subRegion ); if( wellControls.isProducer() ) { - wellControls.forSubGroups< MinimumBHPConstraint, ProductionConstraint< VolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, ProductionConstraint< PhaseVolumeRateConstraint > >( [&]( - auto & constraint ) + wellControls.forSubGroups< MinimumBHPConstraint, ProductionConstraint< VolumeRateConstraint >, ProductionConstraint< MassRateConstraint >, + ProductionConstraint< PhaseVolumeRateConstraint > >( [&]( + auto + & constraint ) { - if( ConstraintTypeId(wellControls.getControl()) == constraint.getControl() ) + if( ConstraintTypeId( wellControls.getControl()) == constraint.getControl() ) { wellControls.setCurrentConstraint( &constraint ); } @@ -1738,9 +1742,12 @@ void CompositionalMultiphaseWell::initializeWell( DomainPartition & domain, Mesh } else { - wellControls.forSubGroups< MaximumBHPConstraint, InjectionConstraint< VolumeRateConstraint >, InjectionConstraint< MassRateConstraint >, InjectionConstraint< PhaseVolumeRateConstraint > >( [&]( auto & constraint ) + wellControls.forSubGroups< MaximumBHPConstraint, InjectionConstraint< VolumeRateConstraint >, InjectionConstraint< MassRateConstraint >, InjectionConstraint< PhaseVolumeRateConstraint > >( [&]( + auto + & + constraint ) { - if( ConstraintTypeId(wellControls.getControl()) == constraint.getControl() ) + if( ConstraintTypeId( wellControls.getControl()) == constraint.getControl() ) { wellControls.setCurrentConstraint( &constraint ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPropWriter.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPropWriter.hpp index c9accc4f717..ea8a019a4dd 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPropWriter.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellPropWriter.hpp @@ -161,7 +161,7 @@ class WellPropWriter stream << "," << m_prop[er][esr][ei][i]; } }; - template< typename T > struct typed_2d_perf_res_prop_writer : public perf_prop_writer + template< typename T > struct typed_2d_perf_res_prop_writer : public perf_prop_writer { typedef T value_type; typedef typed_prop_wrapper< value_type > prop_wrapper_type; @@ -398,7 +398,7 @@ class WellPropWriter } m_perfPropWriterVec.push_back( new typed_2d_perf_res_prop_writer( prop, m_numComponent )); } - + template< typename T > void registerPerfResPhaseComponentProp( std::string const & name, const T & prop ) { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp index 9c71ab571f0..fc602bc3bd3 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp @@ -507,12 +507,12 @@ void WellSolverBase::assembleWellSystem( real64 const time_n, computeWellPerforationRates( time_n, dt, elementRegionManager, subRegion ); assembleWellFluxTerms( time_n, dt, subRegion, dofManager, localMatrix.toViewConstSizes(), localRhs ); my_ctime=my_ctime+1; - - // auto iterInfo = currentIter( time_n, dt ); - // outputWellDebug( time_n, dt, std::get< 0 >( iterInfo ), std::get< 1 >( iterInfo ), std::get< 2 >( iterInfo ), - // domain, dofManager, localMatrix, localRhs ); - - + + // auto iterInfo = currentIter( time_n, dt ); + // outputWellDebug( time_n, dt, std::get< 0 >( iterInfo ), std::get< 1 >( iterInfo ), std::get< 2 >( iterInfo ), + // domain, dofManager, localMatrix, localRhs ); + + } void WellSolverBase::assembleSystem( real64 const time, From 44902df8cda2f97b9b17577a78377cfc3ce0fc26 Mon Sep 17 00:00:00 2001 From: Tom Byer <149726499+tjb-ltk@users.noreply.github.com> Date: Mon, 3 Nov 2025 12:41:07 -0800 Subject: [PATCH 41/41] missing from merge --- .../wells/CompositionalMultiphaseWell.hpp | 4 ---- .../fluidFlow/wells/SinglePhaseWell.hpp | 7 +++++++ .../fluidFlow/wells/WellSolverBase.cpp | 14 +++++++------- .../fluidFlow/wells/WellSolverBase.hpp | 6 ++---- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp index 7d27ddb2589..16bc0f14555 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.hpp @@ -425,8 +425,6 @@ class CompositionalMultiphaseWell : public WellSolverBase } viewKeysCompMultiphaseWell; - void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) override; - virtual void saveState( WellElementSubRegion & subRegion ) override; protected: @@ -498,8 +496,6 @@ class CompositionalMultiphaseWell : public WellSolverBase * @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; - virtual void setConstitutiveNames( ElementSubRegionBase & subRegion ) const override; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp index 9a347cba825..5c7c9f0bdb2 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.hpp @@ -336,6 +336,13 @@ class SinglePhaseWell : public WellSolverBase DofManager const & dofManager, 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 diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp index fc602bc3bd3..3fe22216f07 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp @@ -116,7 +116,7 @@ void WellSolverBase::postInputInitialization() // 1. Set key dimensions of the problem m_numDofPerWellElement = m_isThermal ? m_numComponents + 2 : m_numComponents + 1; // 1 pressure connectionRate + temp if thermal m_numDofPerResElement = m_isThermal ? m_numComponents + 1: m_numComponents; // 1 pressure + temp if thermal - m_writeSegDebug=2; + m_writeSegDebug=0; if( m_writeSegDebug > 0 ) { if( m_writeCSV == 0 ) @@ -787,7 +787,7 @@ bool WellSolverBase::solveNonlinearSystem( real64 const & time_n, GEOS_FMT( " Well: {} Est Attempt: NewtonIter: {:2}", subRegion.getName(), stepDt, newtonIter )); { - Timer timer( m_timers["assemble"] ); + Timer timer( m_timers.get_inserted( "assemble" ) ); // We sync the nonlinear convergence history. The coupled solver parameters are the one being // used. We want to propagate the info to subsolvers. It can be important for solvers that @@ -833,7 +833,7 @@ bool WellSolverBase::solveNonlinearSystem( real64 const & time_n, mesh, subRegion, dofManager, m_localMatrix.toViewConstSizes(), m_rhs.values() ); real64 residualNorm = 0; { - Timer timer( m_timers["convergence check"] ); + Timer timer( m_timers.get_inserted( "convergence check" ) ); // get residual norm residualNorm = calculateWellResidualNorm( time_n, stepDt, subRegion, dofManager, m_rhs.values() ); @@ -931,7 +931,7 @@ bool WellSolverBase::solveNonlinearSystem( real64 const & time_n, } { - Timer timer( m_timers["linear solver total"] ); + Timer timer( m_timers.get_inserted( "linear solver total" ) ); // if using adaptive Krylov tolerance scheme, update tolerance. LinearSolverParameters::Krylov & krylovParams = m_linearSolverParameters.get().krylov; @@ -947,7 +947,7 @@ bool WellSolverBase::solveNonlinearSystem( real64 const & time_n, } { - Timer timer_setup( m_timers["linear solver create"] ); + Timer timer_setup( m_timers.get_inserted( "linear solver create" ) ); // Compose parallel LA matrix/rhs out of local LA matrix/rhs // @@ -969,7 +969,7 @@ bool WellSolverBase::solveNonlinearSystem( real64 const & time_n, } { - Timer timer( m_timers["apply solution"] ); + Timer timer( m_timers.get_inserted( "apply solution" ) ); // Compute the scaling factor for the Newton update scaleFactor = scalingForWellSystemSolution( subRegion, dofManager, m_solution.values() ); @@ -990,7 +990,7 @@ bool WellSolverBase::solveNonlinearSystem( real64 const & time_n, } { - Timer timer( m_timers["update state"] ); + Timer timer( m_timers.get_inserted( "update state" ) ); // update derived variables (constitutive models) updateWellState( subRegion ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp index 0396c3e7d0d..9d8ea0d26d6 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.hpp @@ -332,14 +332,14 @@ class WellSolverBase : public PhysicsSolverBase */ virtual real64 updateWellState( WellElementSubRegion & subRegion ) = 0; virtual void updateState( DomainPartition & domain ) override; - + virtual void saveState( WellElementSubRegion & subRegion ) = 0; /** * @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; - virtual void saveState( WellElementSubRegion & subRegion ) = 0; + /** * @brief Recompute all dependent quantities from primary variables (including constitutive * models) @@ -397,8 +397,6 @@ class WellSolverBase : public PhysicsSolverBase WellElementSubRegion & subregion, DofManager const & dofManager ); - virtual void initializeWell( DomainPartition & domain, MeshLevel & mesh, WellElementSubRegion & subRegion, real64 const & time_n ) = 0; - /** * @brief Function to perform line search * @param time_n time at the beginning of the step