From e70a4bd348b5859446806b3bb302e5797e3be29e Mon Sep 17 00:00:00 2001 From: Francois Hamon Date: Wed, 17 Feb 2021 09:37:54 -0800 Subject: [PATCH 01/10] implemented CO2Brine with new tables and without autodiff --- .../constitutive/CMakeLists.txt | 22 +- .../contact/ContactRelationBase.cpp | 16 +- .../NewMultiPhaseMultiComponentFluid.cpp | 182 ++++ .../NewMultiPhaseMultiComponentFluid.hpp | 870 ++++++++++++++++++ .../NewBrineCO2DensityFunction.cpp | 173 ++++ .../NewBrineCO2DensityFunction.hpp | 226 +++++ .../NewBrineViscosityFunction.cpp | 78 ++ .../NewBrineViscosityFunction.hpp | 142 +++ .../PVTFunctions/NewCO2SolubilityFunction.cpp | 321 +++++++ .../PVTFunctions/NewCO2SolubilityFunction.hpp | 298 ++++++ .../NewFenghourCO2ViscosityFunction.cpp | 157 ++++ .../NewFenghourCO2ViscosityFunction.hpp | 148 +++ .../fluid/PVTFunctions/NewFlashModelBase.hpp | 124 +++ .../fluid/PVTFunctions/NewPVTFunctionBase.hpp | 124 +++ .../NewSpanWagnerCO2DensityFunction.cpp | 316 +++++++ .../NewSpanWagnerCO2DensityFunction.hpp | 165 ++++ .../constitutive/fluid/multiFluidSelector.hpp | 7 +- .../constitutive/unitTests/CMakeLists.txt | 3 +- .../unitTests/testCO2BrinePVTModels.cpp | 734 +++++++++++++++ .../constitutive/unitTests/testMultiFluid.cpp | 311 ++++++- .../fileIO/schema/docs/Constitutive.rst | 1 + .../fileIO/schema/docs/Constitutive_other.rst | 1 + .../docs/NewMultiPhaseMultiComponentFluid.rst | 14 + ...NewMultiPhaseMultiComponentFluid_other.rst | 33 + src/coreComponents/fileIO/schema/schema.xsd | 15 + .../fileIO/schema/schema.xsd.other | 53 ++ .../managers/Functions/TableFunction.cpp | 229 +++-- .../managers/Functions/TableFunction.hpp | 314 ++++++- .../managers/unitTests/testFunctions.cpp | 231 ++++- src/docs/sphinx/CompleteXMLSchema.rst | 14 + 30 files changed, 5118 insertions(+), 204 deletions(-) create mode 100644 src/coreComponents/constitutive/fluid/NewMultiPhaseMultiComponentFluid.cpp create mode 100644 src/coreComponents/constitutive/fluid/NewMultiPhaseMultiComponentFluid.hpp create mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.cpp create mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.hpp create mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.cpp create mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.hpp create mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.cpp create mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.hpp create mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.cpp create mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.hpp create mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewFlashModelBase.hpp create mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewPVTFunctionBase.hpp create mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.cpp create mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.hpp create mode 100644 src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp create mode 100644 src/coreComponents/fileIO/schema/docs/NewMultiPhaseMultiComponentFluid.rst create mode 100644 src/coreComponents/fileIO/schema/docs/NewMultiPhaseMultiComponentFluid_other.rst diff --git a/src/coreComponents/constitutive/CMakeLists.txt b/src/coreComponents/constitutive/CMakeLists.txt index 9c648804f49..edac324379c 100644 --- a/src/coreComponents/constitutive/CMakeLists.txt +++ b/src/coreComponents/constitutive/CMakeLists.txt @@ -13,14 +13,22 @@ set( constitutive_headers capillaryPressure/VanGenuchtenCapillaryPressure.hpp contact/ContactRelationBase.hpp contact/Coulomb.hpp - fluid/MultiPhaseMultiComponentFluid.hpp + fluid/MultiPhaseMultiComponentFluid.hpp + fluid/NewMultiPhaseMultiComponentFluid.hpp fluid/PVTFunctions/BrineCO2DensityFunction.hpp + fluid/PVTFunctions/NewBrineCO2DensityFunction.hpp fluid/PVTFunctions/BrineViscosityFunction.hpp + fluid/PVTFunctions/NewBrineViscosityFunction.hpp fluid/PVTFunctions/CO2SolubilityFunction.hpp + fluid/PVTFunctions/NewCO2SolubilityFunction.hpp fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp + fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.hpp fluid/PVTFunctions/FlashModelBase.hpp + fluid/PVTFunctions/NewFlashModelBase.hpp fluid/PVTFunctions/PVTFunctionBase.hpp + fluid/PVTFunctions/NewPVTFunctionBase.hpp fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp + fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.hpp fluid/PVTFunctions/UtilityFunctions.hpp fluid/SingleFluidBase.hpp fluid/singleFluidSelector.hpp @@ -69,12 +77,18 @@ set( constitutive_sources contact/ContactRelationBase.cpp contact/Coulomb.cpp fluid/CompressibleSinglePhaseFluid.cpp - fluid/MultiPhaseMultiComponentFluid.cpp + fluid/MultiPhaseMultiComponentFluid.cpp + fluid/NewMultiPhaseMultiComponentFluid.cpp fluid/PVTFunctions/BrineCO2DensityFunction.cpp - fluid/PVTFunctions/BrineViscosityFunction.cpp + fluid/PVTFunctions/NewBrineCO2DensityFunction.cpp + fluid/PVTFunctions/BrineViscosityFunction.cpp + fluid/PVTFunctions/NewBrineViscosityFunction.cpp fluid/PVTFunctions/CO2SolubilityFunction.cpp + fluid/PVTFunctions/NewCO2SolubilityFunction.cpp fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp - fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp + fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.cpp + fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp + fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.cpp fluid/PVTFunctions/UtilityFunctions.cpp fluid/SingleFluidBase.cpp fluid/MultiFluidBase.cpp diff --git a/src/coreComponents/constitutive/contact/ContactRelationBase.cpp b/src/coreComponents/constitutive/contact/ContactRelationBase.cpp index 87a2335e10e..25fae1a15f9 100644 --- a/src/coreComponents/constitutive/contact/ContactRelationBase.cpp +++ b/src/coreComponents/constitutive/contact/ContactRelationBase.cpp @@ -108,15 +108,16 @@ void ContactRelationBase::initializePreSubGroups( Group * const ) TableFunction * const apertureTable = dynamic_cast< TableFunction * >(m_apertureFunction); if( apertureTable!=nullptr ) { - array1d< array1d< real64 > > & xvals0 = apertureTable->getCoordinates(); + ArrayOfArraysView< real64 > xvals0 = apertureTable->getCoordinates(); array1d< real64 > & yvals = apertureTable->getValues(); GEOSX_ERROR_IF( xvals0.size() > 1, "Aperture limiter table cannot be greater than a 1d table." ); - array1d< real64 > & xvals = xvals0[0]; + arraySlice1d< real64 > xvals = xvals0[0]; + localIndex const size = xvals.size(); - GEOSX_ERROR_IF( xvals.back() > 0.0 || xvals.back() < 0.0, + GEOSX_ERROR_IF( xvals0( 0, size-1 ) > 0.0 || xvals0( 0, size-1 ) < 0.0, "Invalid aperture limiter table. Last coordinate must be zero!!" ); GEOSX_ERROR_IF( xvals.size() < 2, @@ -130,20 +131,15 @@ void ContactRelationBase::initializePreSubGroups( Group * const ) real64 m_apertureTransition = (yvals[n] - slope * xvals[n] ) / ( 1.0 - slope ); - xvals.emplace_back( m_apertureTransition ); + xvals0.emplaceBack( 0, m_apertureTransition ); yvals.emplace_back( m_apertureTransition ); - xvals.emplace_back( m_apertureTransition*10e9 ); + xvals0.emplaceBack( 0, m_apertureTransition*10e9 ); yvals.emplace_back( m_apertureTransition*10e9 ); apertureTable->reInitializeFunction(); } -// for( int i=0 ; i<200 ; ++i ) -// { -// real64 coord = 0.01*i-1.0; -// std::cout<Evaluate( &coord )< + setInputFlag( InputFlags::REQUIRED )-> + setRestartFlags( RestartFlags::NO_WRITE )-> + setDescription( "Names of the files defining the parameters of the viscosity and density models" ); + + registerWrapper( viewKeyStruct::flashModelParaFileString, &m_flashModelParaFile )-> + setInputFlag( InputFlags::REQUIRED )-> + setRestartFlags( RestartFlags::NO_WRITE )-> + setDescription( "Name of the file defining the parameters of the flash model" ); +} + +NewMultiPhaseMultiComponentFluid::~NewMultiPhaseMultiComponentFluid() +{} + + +std::unique_ptr< ConstitutiveBase > +NewMultiPhaseMultiComponentFluid::deliverClone( string const & name, + Group * const parent ) const +{ + std::unique_ptr< ConstitutiveBase > clone = MultiFluidBase::deliverClone( name, parent ); + + NewMultiPhaseMultiComponentFluid * const newConstitutiveRelation = dynamic_cast< NewMultiPhaseMultiComponentFluid * >(clone.get()); + newConstitutiveRelation->m_phaseGasIndex = this->m_phaseGasIndex; + newConstitutiveRelation->m_phaseLiquidIndex = this->m_phaseLiquidIndex; + + newConstitutiveRelation->createPVTModels(); + + return clone; +} + +void NewMultiPhaseMultiComponentFluid::postProcessInput() +{ + MultiFluidBase::postProcessInput(); + + localIndex const numPhases = numFluidPhases(); + localIndex const numComps = numFluidComponents(); + GEOSX_ERROR_IF( numPhases != 2, "The number of phases in this model should be equal to 2" ); + GEOSX_ERROR_IF( numComps != 2, "The number of components in this model should be equal to 2" ); + GEOSX_ERROR_IF( m_phasePVTParaFiles.size() != 2, "The number of phasePVTParaFiles is not the same as the number of phases!" ); + + bool notFound = true; + for( localIndex i = 0; i < m_phaseNames.size(); ++i ) + { + if( m_phaseNames[i] == "CO2" || m_phaseNames[i] == "co2" || + m_phaseNames[i] == "gas" || m_phaseNames[i] == "Gas" ) + { + m_phaseGasIndex = i; + notFound = false; + break; + } + } + GEOSX_ERROR_IF( notFound, "Phase co2/gas is not found!" ); + + notFound = true; + for( localIndex i = 0; i < m_phaseNames.size(); ++i ) + { + if( m_phaseNames[i] == "Water" || m_phaseNames[i] == "water" || + m_phaseNames[i] == "Liquid" || m_phaseNames[i] == "liquid" ) + { + m_phaseLiquidIndex = i; + notFound = false; + break; + } + } + GEOSX_ERROR_IF( notFound, "Phase water/liquid is not found!" ); + + createPVTModels(); +} + +void NewMultiPhaseMultiComponentFluid::createPVTModels() +{ + // 1) Create the viscosity and density models + for( string & filename : m_phasePVTParaFiles ) + { + std::ifstream is( filename ); + constexpr std::streamsize buf_size = 256; + char buf[buf_size]; + + while( is.getline( buf, buf_size ) ) + { + string const str( buf ); + string_array const strs = Tokenize( str, " " ); + if( strs[0] == "DensityFun" ) + { + if( strs[1] == "SpanWagnerCO2Density" ) + { + m_co2Density = std::make_unique< SpanWagnerCO2Density >( strs, m_componentNames, m_componentMolarWeight ); + } + else if( strs[1] == "BrineCO2Density" ) + { + m_brineDensity = std::make_unique< BrineCO2Density >( strs, m_componentNames, m_componentMolarWeight ); + } + } + else if( strs[0] == "ViscosityFun" ) + { + if( strs[1] == "FenghourCO2Viscosity" ) + { + m_co2Viscosity = std::make_unique< FenghourCO2Viscosity >( strs, m_componentNames, m_componentMolarWeight ); + } + else if( strs[1] == "BrineViscosity" ) + { + m_brineViscosity = std::make_unique< BrineViscosity >( strs, m_componentNames, m_componentMolarWeight ); + } + } + else + { + GEOSX_ERROR( "Error: Invalid PVT function: " << strs[0] << "." ); + } + } + is.close(); + } + + GEOSX_ERROR_IF( m_co2Density == nullptr, "SpanWagnerCO2Density model not found" ); + GEOSX_ERROR_IF( m_brineDensity == nullptr, "BrineCO2Density model not found" ); + GEOSX_ERROR_IF( m_co2Viscosity == nullptr, "FenghourCO2Viscosity model not found" ); + GEOSX_ERROR_IF( m_brineViscosity == nullptr, "BrineViscosity model not found" ); + + // 2) Create the flash model + { + std::ifstream is( m_flashModelParaFile ); + constexpr std::streamsize buf_size = 256; + char buf[buf_size]; + + while( is.getline( buf, buf_size ) ) + { + string const str( buf ); + string_array const strs = Tokenize( str, " " ); + if( strs[0] == "FlashModel" && strs[1] == "CO2Solubility" ) + { + m_co2Solubility = std::make_unique< CO2Solubility >( strs, m_phaseNames, m_componentNames, m_componentMolarWeight ); + } + else + { + GEOSX_ERROR( "Error: Invalid flash model: " << strs[0] << ", " << strs[1] << "." ); + } + } + is.close(); + } + + GEOSX_ERROR_IF( m_co2Solubility == nullptr, "CO2Solubility model not found" ); +} + +REGISTER_CATALOG_ENTRY( ConstitutiveBase, NewMultiPhaseMultiComponentFluid, string const &, Group * const ) + +} //namespace constitutive + +} //namespace geosx diff --git a/src/coreComponents/constitutive/fluid/NewMultiPhaseMultiComponentFluid.hpp b/src/coreComponents/constitutive/fluid/NewMultiPhaseMultiComponentFluid.hpp new file mode 100644 index 00000000000..6f5e3ab4d35 --- /dev/null +++ b/src/coreComponents/constitutive/fluid/NewMultiPhaseMultiComponentFluid.hpp @@ -0,0 +1,870 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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 Total, S.A + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file NewMultiPhaseMultiComponentFluid.hpp + */ + +#ifndef GEOSX_CONSTITUTIVE_FLUID_NEWMULTIPHASEMULTICOMPONENTFLUID_HPP_ +#define GEOSX_CONSTITUTIVE_FLUID_NEWMULTIPHASEMULTICOMPONENTFLUID_HPP_ + +#include "constitutive/fluid/MultiFluidBase.hpp" +#include "constitutive/fluid/MultiFluidUtils.hpp" +#include "PVTFunctions/NewBrineCO2DensityFunction.hpp" +#include "PVTFunctions/NewSpanWagnerCO2DensityFunction.hpp" +#include "PVTFunctions/NewBrineViscosityFunction.hpp" +#include "PVTFunctions/NewFenghourCO2ViscosityFunction.hpp" +#include "PVTFunctions/NewCO2SolubilityFunction.hpp" + +#include + +namespace geosx +{ + +namespace constitutive +{ + +/** + * @brief Kernel wrapper class for NewMultiPhaseMultiComponentFluid. + */ +class NewMultiPhaseMultiComponentFluidUpdate final : public MultiFluidBaseUpdate +{ +public: + + NewMultiPhaseMultiComponentFluidUpdate( localIndex const phaseGasIndex, + localIndex const phaseLiquidIndex, + PVTProps::BrineViscosity & brineViscosity, + PVTProps::FenghourCO2Viscosity & co2Viscosity, + PVTProps::BrineCO2Density & brineDensity, + PVTProps::SpanWagnerCO2Density & co2Density, + PVTProps::CO2Solubility & co2Solubility, + arrayView1d< real64 const > const & componentMolarWeight, + bool useMass, + arrayView3d< real64 > const & phaseFraction, + arrayView3d< real64 > const & dPhaseFraction_dPressure, + arrayView3d< real64 > const & dPhaseFraction_dTemperature, + arrayView4d< real64 > const & dPhaseFraction_dGlobalCompFraction, + arrayView3d< real64 > const & phaseDensity, + arrayView3d< real64 > const & dPhaseDensity_dPressure, + arrayView3d< real64 > const & dPhaseDensity_dTemperature, + arrayView4d< real64 > const & dPhaseDensity_dGlobalCompFraction, + arrayView3d< real64 > const & phaseMassDensity, + arrayView3d< real64 > const & dPhaseMassDensity_dPressure, + arrayView3d< real64 > const & dPhaseMassDensity_dTemperature, + arrayView4d< real64 > const & dPhaseMassDensity_dGlobalCompFraction, + arrayView3d< real64 > const & phaseViscosity, + arrayView3d< real64 > const & dPhaseViscosity_dPressure, + arrayView3d< real64 > const & dPhaseViscosity_dTemperature, + arrayView4d< real64 > const & dPhaseViscosity_dGlobalCompFraction, + arrayView4d< real64 > const & phaseCompFraction, + arrayView4d< real64 > const & dPhaseCompFraction_dPressure, + arrayView4d< real64 > const & dPhaseCompFraction_dTemperature, + arrayView5d< real64 > const & dPhaseCompFraction_dGlobalCompFraction, + arrayView2d< real64 > const & totalDensity, + arrayView2d< real64 > const & dTotalDensity_dPressure, + arrayView2d< real64 > const & dTotalDensity_dTemperature, + arrayView3d< real64 > const & dTotalDensity_dGlobalCompFraction ) + : MultiFluidBaseUpdate( componentMolarWeight, + useMass, + phaseFraction, + dPhaseFraction_dPressure, + dPhaseFraction_dTemperature, + dPhaseFraction_dGlobalCompFraction, + phaseDensity, + dPhaseDensity_dPressure, + dPhaseDensity_dTemperature, + dPhaseDensity_dGlobalCompFraction, + phaseMassDensity, + dPhaseMassDensity_dPressure, + dPhaseMassDensity_dTemperature, + dPhaseMassDensity_dGlobalCompFraction, + phaseViscosity, + dPhaseViscosity_dPressure, + dPhaseViscosity_dTemperature, + dPhaseViscosity_dGlobalCompFraction, + phaseCompFraction, + dPhaseCompFraction_dPressure, + dPhaseCompFraction_dTemperature, + dPhaseCompFraction_dGlobalCompFraction, + totalDensity, + dTotalDensity_dPressure, + dTotalDensity_dTemperature, + dTotalDensity_dGlobalCompFraction ), + m_phaseGasIndex( phaseGasIndex ), + m_phaseLiquidIndex( phaseLiquidIndex ), + m_brineViscosityWrapper( brineViscosity.createKernelWrapper() ), + m_co2ViscosityWrapper( co2Viscosity.createKernelWrapper() ), + m_brineDensityWrapper( brineDensity.createKernelWrapper() ), + m_co2DensityWrapper( co2Density.createKernelWrapper() ), + m_co2SolubilityWrapper( co2Solubility.createKernelWrapper() ) + {} + + /// Default copy constructor + NewMultiPhaseMultiComponentFluidUpdate( NewMultiPhaseMultiComponentFluidUpdate const & ) = default; + + /// Default move constructor + NewMultiPhaseMultiComponentFluidUpdate( NewMultiPhaseMultiComponentFluidUpdate && ) = default; + + /// Deleted copy assignment operator + NewMultiPhaseMultiComponentFluidUpdate & operator=( NewMultiPhaseMultiComponentFluidUpdate const & ) = delete; + + /// Deleted move assignment operator + NewMultiPhaseMultiComponentFluidUpdate & operator=( NewMultiPhaseMultiComponentFluidUpdate && ) = delete; + + GEOSX_HOST_DEVICE + GEOSX_FORCE_INLINE + virtual void compute( real64 const pressure, + real64 const temperature, + arraySlice1d< real64 const > const & composition, + arraySlice1d< real64 > const & phaseFraction, + arraySlice1d< real64 > const & phaseDensity, + arraySlice1d< real64 > const & phaseMassDensity, + arraySlice1d< real64 > const & phaseViscosity, + arraySlice2d< real64 > const & phaseCompFraction, + real64 & totalDensity ) const override; + + GEOSX_HOST_DEVICE + GEOSX_FORCE_INLINE + virtual void compute( real64 const pressure, + real64 const temperature, + arraySlice1d< real64 const > const & composition, + arraySlice1d< real64 > const & phaseFraction, + arraySlice1d< real64 > const & dPhaseFraction_dPressure, + arraySlice1d< real64 > const & dPhaseFraction_dTemperature, + arraySlice2d< real64 > const & dPhaseFraction_dGlobalCompFraction, + arraySlice1d< real64 > const & phaseDensity, + arraySlice1d< real64 > const & dPhaseDensity_dPressure, + arraySlice1d< real64 > const & dPhaseDensity_dTemperature, + arraySlice2d< real64 > const & dPhaseDensity_dGlobalCompFraction, + arraySlice1d< real64 > const & phaseMassDensity, + arraySlice1d< real64 > const & dPhaseMassDensity_dPressure, + arraySlice1d< real64 > const & dPhaseMassDensity_dTemperature, + arraySlice2d< real64 > const & dPhaseMassDensity_dGlobalCompFraction, + arraySlice1d< real64 > const & phaseViscosity, + arraySlice1d< real64 > const & dPhaseViscosity_dPressure, + arraySlice1d< real64 > const & dPhaseViscosity_dTemperature, + arraySlice2d< real64 > const & dPhaseViscosity_dGlobalCompFraction, + arraySlice2d< real64 > const & phaseCompFraction, + arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, + arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, + arraySlice3d< real64 > const & dPhaseCompFraction_dGlobalCompFraction, + real64 & totalDensity, + real64 & dTotalDensity_dPressure, + real64 & dTotalDensity_dTemperature, + arraySlice1d< real64 > const & dTotalDensity_dGlobalCompFraction ) const override; + + GEOSX_HOST_DEVICE + GEOSX_FORCE_INLINE + virtual void update( localIndex const k, + localIndex const q, + real64 const pressure, + real64 const temperature, + arraySlice1d< real64 const > const & composition ) const override + { + compute( pressure, + temperature, + composition, + m_phaseFraction[k][q], + m_dPhaseFraction_dPressure[k][q], + m_dPhaseFraction_dTemperature[k][q], + m_dPhaseFraction_dGlobalCompFraction[k][q], + m_phaseDensity[k][q], + m_dPhaseDensity_dPressure[k][q], + m_dPhaseDensity_dTemperature[k][q], + m_dPhaseDensity_dGlobalCompFraction[k][q], + m_phaseMassDensity[k][q], + m_dPhaseMassDensity_dPressure[k][q], + m_dPhaseMassDensity_dTemperature[k][q], + m_dPhaseMassDensity_dGlobalCompFraction[k][q], + m_phaseViscosity[k][q], + m_dPhaseViscosity_dPressure[k][q], + m_dPhaseViscosity_dTemperature[k][q], + m_dPhaseViscosity_dGlobalCompFraction[k][q], + m_phaseCompFraction[k][q], + m_dPhaseCompFraction_dPressure[k][q], + m_dPhaseCompFraction_dTemperature[k][q], + m_dPhaseCompFraction_dGlobalCompFraction[k][q], + m_totalDensity[k][q], + m_dTotalDensity_dPressure[k][q], + m_dTotalDensity_dTemperature[k][q], + m_dTotalDensity_dGlobalCompFraction[k][q] ); + } + +private: + + /// Index of the gas phase + localIndex const m_phaseGasIndex; + + /// Index of the liquid phase + localIndex const m_phaseLiquidIndex; + + /// Kernel wrapper for brine viscosity updates + PVTProps::BrineViscosity::KernelWrapper const m_brineViscosityWrapper; + + /// Kernel wrapper for CO2 viscosity updates + PVTProps::FenghourCO2Viscosity::KernelWrapper const m_co2ViscosityWrapper; + + /// Kernel wrapper for brine density updates + PVTProps::BrineCO2Density::KernelWrapper const m_brineDensityWrapper; + + /// Kernel wrapper for CO2 density updates + PVTProps::SpanWagnerCO2Density::KernelWrapper const m_co2DensityWrapper; + + /// Kernel wrapper for phase fraction and phase component fraction updates + PVTProps::CO2Solubility::KernelWrapper const m_co2SolubilityWrapper; +}; + +class NewMultiPhaseMultiComponentFluid : public MultiFluidBase +{ +public: + + NewMultiPhaseMultiComponentFluid( string const & name, Group * const parent ); + + virtual ~NewMultiPhaseMultiComponentFluid() override; + + virtual std::unique_ptr< ConstitutiveBase > + deliverClone( string const & name, + Group * const parent ) const override; + + + static string catalogName() { return "NewMultiPhaseMultiComponentFluid"; } + + virtual string getCatalogName() const override { return catalogName(); } + + /// Type of kernel wrapper for in-kernel update + using KernelWrapper = NewMultiPhaseMultiComponentFluidUpdate; + + /** + * @brief Create an update kernel wrapper. + * @return the wrapper + */ + KernelWrapper createKernelWrapper() + { + return KernelWrapper( m_phaseGasIndex, + m_phaseLiquidIndex, + *m_brineViscosity, + *m_co2Viscosity, + *m_brineDensity, + *m_co2Density, + *m_co2Solubility, + m_componentMolarWeight.toViewConst(), + m_useMass, + m_phaseFraction, + m_dPhaseFraction_dPressure, + m_dPhaseFraction_dTemperature, + m_dPhaseFraction_dGlobalCompFraction, + m_phaseDensity, + m_dPhaseDensity_dPressure, + m_dPhaseDensity_dTemperature, + m_dPhaseDensity_dGlobalCompFraction, + m_phaseMassDensity, + m_dPhaseMassDensity_dPressure, + m_dPhaseMassDensity_dTemperature, + m_dPhaseMassDensity_dGlobalCompFraction, + m_phaseViscosity, + m_dPhaseViscosity_dPressure, + m_dPhaseViscosity_dTemperature, + m_dPhaseViscosity_dGlobalCompFraction, + m_phaseCompFraction, + m_dPhaseCompFraction_dPressure, + m_dPhaseCompFraction_dTemperature, + m_dPhaseCompFraction_dGlobalCompFraction, + m_totalDensity, + m_dTotalDensity_dPressure, + m_dTotalDensity_dTemperature, + m_dTotalDensity_dGlobalCompFraction ); + } + + struct viewKeyStruct : MultiFluidBase::viewKeyStruct + { + static constexpr auto flashModelParaFileString = "flashModelParaFile"; + static constexpr auto phasePVTParaFilesString = "phasePVTParaFiles"; + } viewKeysNewMultiPhaseMultiComponentFluid; + + +protected: + + virtual void postProcessInput() override; + +private: + + void createPVTModels(); + + /// Names of the files defining the viscosity and density models + path_array m_phasePVTParaFiles; + + /// Name of the file defining the flash model + Path m_flashModelParaFile; + + /// Index of the gas phase + localIndex m_phaseGasIndex; + + /// Index of the liquid phase + localIndex m_phaseLiquidIndex; + + // TODO: Here I hard-coded all the types to avoid the virtual calls in the compute function. + // See if there is a way to reintroduce them. If it is not possible, the class should be + // renamed because it is not "multi-phase, multi-component", but just CO2-brine. + + /// Pointer to the brine viscosity model + std::unique_ptr< PVTProps::BrineViscosity > m_brineViscosity; + + /// Pointer to the CO2 viscosity model + std::unique_ptr< PVTProps::FenghourCO2Viscosity > m_co2Viscosity; + + /// Pointer to the brine density model + std::unique_ptr< PVTProps::BrineCO2Density > m_brineDensity; + + /// Pointer to the CO2 density model + std::unique_ptr< PVTProps::SpanWagnerCO2Density > m_co2Density; + + /// Pointer to the flash model + std::unique_ptr< PVTProps::CO2Solubility > m_co2Solubility; + +}; + +GEOSX_HOST_DEVICE +GEOSX_FORCE_INLINE +void NewMultiPhaseMultiComponentFluidUpdate::compute( real64 pressure, + real64 temperature, + arraySlice1d< real64 const > const & composition, + arraySlice1d< real64 > const & phaseFraction, + arraySlice1d< real64 > const & phaseDensity, + arraySlice1d< real64 > const & phaseMassDensity, + arraySlice1d< real64 > const & phaseViscosity, + arraySlice2d< real64 > const & phaseCompFraction, + real64 & totalDensity ) const +{ + constexpr localIndex numComps = 2; + constexpr localIndex numPhases = 2; + localIndex const ipGas = m_phaseGasIndex; + localIndex const ipLiq = m_phaseLiquidIndex; + + // for now, compute the derivatives and discard them + stackArray1d< real64, numPhases > dPhaseFrac_dPres( numPhases ); + stackArray1d< real64, numPhases > dPhaseFrac_dTemp( numPhases ); + stackArray2d< real64, numPhases *numComps > dPhaseFrac_dComp( numPhases, numComps ); + stackArray2d< real64, numPhases *numComps > dPhaseCompFrac_dPres( numPhases, numComps ); + stackArray2d< real64, numPhases *numComps > dPhaseCompFrac_dTemp( numPhases, numComps ); + stackArray3d< real64, numPhases *numComps *numComps > dPhaseCompFrac_dComp( numPhases, numComps, numComps ); + real64 dPhaseDens_dPres = 0.0; + real64 dPhaseDens_dTemp = 0.0; + stackArray1d< real64, numComps > dPhaseDens_dComp( numComps ); + real64 dPhaseMassDens_dPres = 0.0; + real64 dPhaseMassDens_dTemp = 0.0; + stackArray1d< real64, numComps > dPhaseMassDens_dComp( numComps ); + real64 dPhaseVisc_dPres = 0.0; + real64 dPhaseVisc_dTemp = 0.0; + stackArray1d< real64, numComps > dPhaseVisc_dComp( numComps ); + + // 1. Convert input mass fractions to mole fractions and keep derivatives + + stackArray1d< real64, numComps > compMoleFrac( numComps ); + if( m_useMass ) + { + real64 totalMolality = 0.0; + for( localIndex ic = 0; ic < numComps; ++ic ) + { + real64 const mwInv = 1.0 / m_componentMolarWeight[ic]; + compMoleFrac[ic] = composition[ic] * mwInv; // this is molality (units of mole/mass) + totalMolality += compMoleFrac[ic]; + } + + real64 const totalMolalityInv = 1.0 / totalMolality; + for( localIndex ic = 0; ic < numComps; ++ic ) + { + compMoleFrac[ic] *= totalMolalityInv; + } + } + else + { + for( localIndex ic = 0; ic < numComps; ++ic ) + { + compMoleFrac[ic] = composition[ic]; + } + } + + // 2. Compute phase fractions and phase component fractions + + real64 const temperatureInCelsius = temperature - 273.15; + m_co2SolubilityWrapper.compute( pressure, + temperatureInCelsius, + compMoleFrac, + phaseFraction, dPhaseFrac_dPres, dPhaseFrac_dTemp, dPhaseFrac_dComp, + phaseCompFraction, dPhaseCompFrac_dPres, dPhaseCompFrac_dTemp, dPhaseCompFrac_dComp ); + + // 3. Compute phase densities and phase viscosities + + m_co2DensityWrapper.compute( pressure, + temperatureInCelsius, + phaseCompFraction[ipGas], + phaseDensity[ipGas], dPhaseDens_dPres, dPhaseDens_dTemp, dPhaseDens_dComp, + m_useMass ); + m_co2ViscosityWrapper.compute( pressure, + temperatureInCelsius, + phaseCompFraction[ipGas], + phaseViscosity[ipGas], dPhaseVisc_dPres, dPhaseVisc_dTemp, dPhaseVisc_dComp, + m_useMass ); + + m_brineDensityWrapper.compute( pressure, + temperatureInCelsius, + phaseCompFraction[ipLiq], + phaseDensity[ipLiq], dPhaseDens_dPres, dPhaseDens_dTemp, dPhaseDens_dComp, + m_useMass ); + m_brineViscosityWrapper.compute( pressure, + temperatureInCelsius, + phaseCompFraction[ipLiq], + phaseViscosity[ipLiq], dPhaseVisc_dPres, dPhaseVisc_dTemp, dPhaseVisc_dComp, + m_useMass ); + + // 4. Depending on the m_useMass flag, convert to mass variables or simply compute mass density + + // TODO: for now the treatment of molar/mass density requires too many interpolations in the tables, it needs to be fixed + // we should modify the PVT functions so that they can return phaseMassDens, phaseDens, and phaseMW in one call + // TODO: extract the following piece of code and write a function that can be used here and in MultiFluidPVTPackageWrapper + + if( m_useMass ) + { + // 4.1. Convert phase fractions (requires two passes) + real64 totalMass{}; + + // 4.1.0. Compute the phase molecular weights (ultimately, get that from the PVT function) + real64 phaseMW[2]{}; + real64 phaseMolarDens = 0.0; + real64 dPhaseMolarDens_dPres = 0.0; + real64 dPhaseMolarDens_dTemp = 0.0; + stackArray1d< real64, numComps > dPhaseMolarDens_dComp( 2 ); + m_co2DensityWrapper.compute( pressure, + temperatureInCelsius, + phaseCompFraction[ipGas], + phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, + 0 ); + phaseMW[ipGas] = phaseDensity[ipGas] / phaseMolarDens; + m_brineDensityWrapper.compute( pressure, + temperatureInCelsius, + phaseCompFraction[ipLiq], + phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, + 0 ); + phaseMW[ipLiq] = phaseDensity[ipLiq] / phaseMolarDens; + + // 4.1.1. Compute mass of each phase and total mass (on a 1-mole basis) + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + phaseFraction[ip] *= phaseMW[ip]; + totalMass += phaseFraction[ip]; + } + // 4.1.2. Normalize to get mass fractions + real64 const totalMassInv = 1.0 / totalMass; + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + phaseFraction[ip] *= totalMassInv; + } + // 4.2. Convert phase compositions + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + real64 const phaseMWInv = 1.0 / phaseMW[ip]; + + for( localIndex ic = 0; ic < numComps; ++ic ) + { + real64 const compMW = m_componentMolarWeight[ic]; + phaseCompFraction[ip][ic] = phaseCompFraction[ip][ic] * compMW * phaseMWInv; + } + } + // 4.3 Copy the phase densities into the phase mass densities + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + phaseMassDensity[ip] = phaseDensity[ip]; + } + } + else + { + // for now, we have to compute the phase mass density here + m_co2DensityWrapper.compute( pressure, + temperatureInCelsius, + phaseCompFraction[ipGas], + phaseMassDensity[ipGas], dPhaseMassDens_dPres, + dPhaseMassDens_dTemp, dPhaseMassDens_dComp, + true ); + m_brineDensityWrapper.compute( pressure, + temperatureInCelsius, + phaseCompFraction[ipLiq], + phaseMassDensity[ipLiq], dPhaseMassDens_dPres, + dPhaseMassDens_dTemp, dPhaseMassDens_dComp, + true ); + } + + // TODO: extract the following piece of code and write a function that can be used here and in MultiFluidPVTPackageWrapper + + // 5. Compute total fluid mass/molar density and derivatives + { + totalDensity = 0.0; + // 5.1. Sum mass/molar fraction/density ratio over all phases to get the inverse of density + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + real64 const densInv = 1.0 / phaseDensity[ip]; + real64 const value = phaseFraction[ip] * densInv; + totalDensity += value; + } + // 5.2. Invert the previous quantity to get actual density + totalDensity = 1.0 / totalDensity; + } +} + +GEOSX_HOST_DEVICE +GEOSX_FORCE_INLINE +void NewMultiPhaseMultiComponentFluidUpdate::compute( real64 pressure, + real64 temperature, + arraySlice1d< real64 const > const & composition, + arraySlice1d< real64 > const & phaseFraction, + arraySlice1d< real64 > const & dPhaseFraction_dPressure, + arraySlice1d< real64 > const & dPhaseFraction_dTemperature, + arraySlice2d< real64 > const & dPhaseFraction_dGlobalCompFraction, + arraySlice1d< real64 > const & phaseDensity, + arraySlice1d< real64 > const & dPhaseDensity_dPressure, + arraySlice1d< real64 > const & dPhaseDensity_dTemperature, + arraySlice2d< real64 > const & dPhaseDensity_dGlobalCompFraction, + arraySlice1d< real64 > const & phaseMassDensity, + arraySlice1d< real64 > const & dPhaseMassDensity_dPressure, + arraySlice1d< real64 > const & dPhaseMassDensity_dTemperature, + arraySlice2d< real64 > const & dPhaseMassDensity_dGlobalCompFraction, + arraySlice1d< real64 > const & phaseViscosity, + arraySlice1d< real64 > const & dPhaseViscosity_dPressure, + arraySlice1d< real64 > const & dPhaseViscosity_dTemperature, + arraySlice2d< real64 > const & dPhaseViscosity_dGlobalCompFraction, + arraySlice2d< real64 > const & phaseCompFraction, + arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, + arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, + arraySlice3d< real64 > const & dPhaseCompFraction_dGlobalCompFraction, + real64 & totalDensity, + real64 & dTotalDensity_dPressure, + real64 & dTotalDensity_dTemperature, + arraySlice1d< real64 > const & dTotalDensity_dGlobalCompFraction ) const +{ + // 0. make shortcut structs to avoid long names (TODO maybe remove) + CompositionalVarContainer< 1 > phaseFrac { + phaseFraction, + dPhaseFraction_dPressure, + dPhaseFraction_dTemperature, + dPhaseFraction_dGlobalCompFraction + }; + + CompositionalVarContainer< 1 > phaseDens { + phaseDensity, + dPhaseDensity_dPressure, + dPhaseDensity_dTemperature, + dPhaseDensity_dGlobalCompFraction + }; + + CompositionalVarContainer< 1 > phaseMassDens { + phaseMassDensity, + dPhaseMassDensity_dPressure, + dPhaseMassDensity_dTemperature, + dPhaseMassDensity_dGlobalCompFraction + }; + + CompositionalVarContainer< 1 > phaseVisc { + phaseViscosity, + dPhaseViscosity_dPressure, + dPhaseViscosity_dTemperature, + dPhaseViscosity_dGlobalCompFraction + }; + + CompositionalVarContainer< 2 > phaseCompFrac { + phaseCompFraction, + dPhaseCompFraction_dPressure, + dPhaseCompFraction_dTemperature, + dPhaseCompFraction_dGlobalCompFraction + }; + + CompositionalVarContainer< 0 > totalDens { + totalDensity, + dTotalDensity_dPressure, + dTotalDensity_dTemperature, + dTotalDensity_dGlobalCompFraction + }; + +#if defined(__CUDACC__) + // For some reason nvcc thinks these aren't used. + GEOSX_UNUSED_VAR( phaseFrac, phaseDens, phaseMassDens, phaseVisc, phaseCompFrac, totalDens ); +#endif + + constexpr localIndex numComps = 2; + constexpr localIndex numPhases = 2; + localIndex const ipGas = m_phaseGasIndex; + localIndex const ipLiq = m_phaseLiquidIndex; + + // 1. Convert input mass fractions to mole fractions and keep derivatives + + stackArray1d< real64, numComps > compMoleFrac( numComps ); + stackArray2d< real64, numComps *numComps > dCompMoleFrac_dCompMassFrac( numComps, numComps ); + + if( m_useMass ) + { + real64 totalMolality = 0.0; + for( localIndex ic = 0; ic < numComps; ++ic ) + { + real64 const mwInv = 1.0 / m_componentMolarWeight[ic]; + compMoleFrac[ic] = composition[ic] * mwInv; // this is molality (units of mole/mass) + dCompMoleFrac_dCompMassFrac[ic][ic] = mwInv; + totalMolality += compMoleFrac[ic]; + } + + real64 const totalMolalityInv = 1.0 / totalMolality; + for( localIndex ic = 0; ic < numComps; ++ic ) + { + compMoleFrac[ic] *= totalMolalityInv; + + for( localIndex jc = 0; jc < numComps; ++jc ) + { + dCompMoleFrac_dCompMassFrac[ic][jc] -= compMoleFrac[ic] / m_componentMolarWeight[jc]; + dCompMoleFrac_dCompMassFrac[ic][jc] *= totalMolalityInv; + } + } + } + else + { + for( localIndex ic = 0; ic < numComps; ++ic ) + { + compMoleFrac[ic] = composition[ic]; + } + } + + // 2. Compute phase fractions and phase component fractions + + real64 const temperatureInCelsius = temperature - 273.15; + m_co2SolubilityWrapper.compute( pressure, + temperatureInCelsius, + compMoleFrac, + phaseFrac.value, phaseFrac.dPres, phaseFrac.dTemp, phaseFrac.dComp, + phaseCompFrac.value, phaseCompFrac.dPres, phaseCompFrac.dTemp, phaseCompFrac.dComp ); + + // 3. Compute phase densities and phase viscosities + + m_co2DensityWrapper.compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ipGas], + phaseDens.value[ipGas], phaseDens.dPres[ipGas], phaseDens.dTemp[ipGas], phaseDens.dComp[ipGas], + m_useMass ); + m_co2ViscosityWrapper.compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ipGas], + phaseVisc.value[ipGas], phaseVisc.dPres[ipGas], phaseVisc.dTemp[ipGas], phaseVisc.dComp[ipGas], + m_useMass ); + + m_brineDensityWrapper.compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ipLiq], + phaseDens.value[ipLiq], phaseDens.dPres[ipLiq], phaseDens.dTemp[ipLiq], phaseDens.dComp[ipLiq], + m_useMass ); + m_brineViscosityWrapper.compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ipLiq], + phaseVisc.value[ipLiq], phaseVisc.dPres[ipLiq], phaseVisc.dTemp[ipLiq], phaseVisc.dComp[ipLiq], + m_useMass ); + + // 4. Depending on the m_useMass flag, convert to mass variables or simply compute mass density + + // TODO: for now the treatment of molar/mass density requires too many interpolations in the tables, it needs to be fixed + // we should modify the PVT functions so that they can return phaseMassDens, phaseDens, and phaseMW in one call + // TODO: extract the following piece of code and write a function that can be used here and in MultiFluidPVTPackageWrapper + + if( m_useMass ) + { + // 4.1. Convert phase fractions (requires two passes) + real64 totalMass{}; + real64 dTotalMass_dP{}; + real64 dTotalMass_dT{}; + real64 dTotalMass_dC[2]{}; + + // 4.1.0. Compute the phase molecular weights (ultimately, get that from the PVT function) + real64 phaseMW[2]{}; + real64 dPhaseMW_dPres[2]{}; + real64 dPhaseMW_dTemp[2]{}; + real64 dPhaseMW_dComp[2][2]{}; + real64 phaseMolarDens = 0.0; + real64 dPhaseMolarDens_dPres = 0.0; + real64 dPhaseMolarDens_dTemp = 0.0; + stackArray1d< real64, numComps > dPhaseMolarDens_dComp( 2 ); + m_co2DensityWrapper.compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ipGas], + phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, + 0 ); + phaseMW[ipGas] = phaseDens.value[ipGas] / phaseMolarDens; + dPhaseMW_dPres[ipGas] = phaseDens.dPres[ipGas] / phaseMolarDens - phaseMW[ipGas]*dPhaseMolarDens_dPres / phaseMolarDens; + dPhaseMW_dTemp[ipGas] = phaseDens.dTemp[ipGas] / phaseMolarDens - phaseMW[ipGas]*dPhaseMolarDens_dTemp / phaseMolarDens; + for( localIndex ic = 0; ic < numComps; ++ic ) + { + dPhaseMW_dComp[ipGas][ic] = phaseDens.dComp[ipGas][ic] / phaseMolarDens - phaseMW[ipGas]*dPhaseMolarDens_dComp[ic] / phaseMolarDens; + } + m_brineDensityWrapper.compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ipLiq], + phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, + 0 ); + phaseMW[ipLiq] = phaseDens.value[ipLiq] / phaseMolarDens; + dPhaseMW_dPres[ipLiq] = phaseDens.dPres[ipLiq] / phaseMolarDens - phaseMW[ipLiq]*dPhaseMolarDens_dPres / phaseMolarDens; + dPhaseMW_dTemp[ipLiq] = phaseDens.dTemp[ipLiq] / phaseMolarDens - phaseMW[ipLiq]*dPhaseMolarDens_dTemp / phaseMolarDens; + for( localIndex ic = 0; ic < numComps; ++ic ) + { + dPhaseMW_dComp[ipLiq][ic] = phaseDens.dComp[ipLiq][ic] / phaseMolarDens - phaseMW[ipLiq]*dPhaseMolarDens_dComp[ic]/phaseMolarDens; + } + + + // 4.1.1. Compute mass of each phase and total mass (on a 1-mole basis) + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + real64 const nu = phaseFrac.value[ip]; + + phaseFrac.value[ip] *= phaseMW[ip]; + phaseFrac.dPres[ip] = phaseFrac.dPres[ip] * phaseMW[ip] + nu * dPhaseMW_dPres[ip]; + phaseFrac.dTemp[ip] = phaseFrac.dTemp[ip] * phaseMW[ip] + nu * dPhaseMW_dTemp[ip]; + + totalMass += phaseFrac.value[ip]; + dTotalMass_dP += phaseFrac.dPres[ip]; + dTotalMass_dT += phaseFrac.dTemp[ip]; + + for( localIndex jc = 0; jc < numComps; ++jc ) + { + phaseFrac.dComp[ip][jc] = phaseFrac.dComp[ip][jc] * phaseMW[ip] + nu * dPhaseMW_dComp[ip][jc]; + dTotalMass_dC[jc] += phaseFrac.dComp[ip][jc]; + } + } + + // 4.1.2. Normalize to get mass fractions + real64 const totalMassInv = 1.0 / totalMass; + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + phaseFrac.value[ip] *= totalMassInv; + phaseFrac.dPres[ip] = ( phaseFrac.dPres[ip] - phaseFrac.value[ip] * dTotalMass_dP ) * totalMassInv; + phaseFrac.dTemp[ip] = ( phaseFrac.dTemp[ip] - phaseFrac.value[ip] * dTotalMass_dT ) * totalMassInv; + + for( localIndex jc = 0; jc < numComps; ++jc ) + { + phaseFrac.dComp[ip][jc] = ( phaseFrac.dComp[ip][jc] - phaseFrac.value[ip] * dTotalMass_dC[jc] ) * totalMassInv; + } + } + + // 4.2. Convert phase compositions + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + real64 const phaseMWInv = 1.0 / phaseMW[ip]; + + for( localIndex ic = 0; ic < numComps; ++ic ) + { + + real64 const compMW = m_componentMolarWeight[ic]; + + phaseCompFrac.value[ip][ic] = phaseCompFrac.value[ip][ic] * compMW * phaseMWInv; + phaseCompFrac.dPres[ip][ic] = + ( phaseCompFrac.dPres[ip][ic] * compMW - phaseCompFrac.value[ip][ic] * dPhaseMW_dPres[ip] ) * phaseMWInv; + phaseCompFrac.dTemp[ip][ic] = + ( phaseCompFrac.dTemp[ip][ic] * compMW - phaseCompFrac.value[ip][ic] * dPhaseMW_dTemp[ip] ) * phaseMWInv; + + for( localIndex jc = 0; jc < numComps; ++jc ) + { + phaseCompFrac.dComp[ip][ic][jc] = + ( phaseCompFrac.dComp[ip][ic][jc] * compMW - phaseCompFrac.value[ip][ic] * dPhaseMW_dComp[ip][jc] ) * phaseMWInv; + } + } + } + + // 4.3. Update derivatives w.r.t. mole fractions to derivatives w.r.t mass fractions + real64 work[numComps]{}; + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + applyChainRuleInPlace( numComps, dCompMoleFrac_dCompMassFrac, phaseFrac.dComp[ip], work ); + applyChainRuleInPlace( numComps, dCompMoleFrac_dCompMassFrac, phaseDens.dComp[ip], work ); + + for( localIndex ic = 0; ic < numComps; ++ic ) + { + applyChainRuleInPlace( numComps, dCompMoleFrac_dCompMassFrac, phaseCompFrac.dComp[ip][ic], work ); + } + } + + // 4.4 Copy the phase densities into the phase mass densities + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + phaseMassDens.value[ip] = phaseDens.value[ip]; + phaseMassDens.dPres[ip] = phaseDens.dPres[ip]; + phaseMassDens.dTemp[ip] = phaseDens.dTemp[ip]; + for( localIndex ic = 0; ic < numComps; ++ic ) + { + phaseMassDens.dComp[ip][ic] = phaseDens.dComp[ip][ic]; + } + } + } + else + { + // for now, we have to compute the phase mass density here + m_co2DensityWrapper.compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ipGas], + phaseMassDens.value[ipGas], phaseMassDens.dPres[ipGas], + phaseMassDens.dTemp[ipGas], phaseMassDens.dComp[ipGas], + true ); + m_brineDensityWrapper.compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ipLiq], + phaseMassDens.value[ipLiq], phaseMassDens.dPres[ipLiq], + phaseMassDens.dTemp[ipLiq], phaseMassDens.dComp[ipLiq], + true ); + } + + // TODO: extract the following piece of code and write a function that can be used here and in MultiFluidPVTPackageWrapper + + // 5. Compute total fluid mass/molar density and derivatives + { + totalDens.value = 0.0; + totalDens.dPres = 0.0; + totalDens.dTemp = 0.0; + for( localIndex jc = 0; jc < numComps; ++jc ) + { + totalDens.dComp[jc] = 0.0; + } + + // 5.1. Sum mass/molar fraction/density ratio over all phases to get the inverse of density + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + real64 const densInv = 1.0 / phaseDens.value[ip]; + real64 const value = phaseFrac.value[ip] * densInv; + + totalDens.value += value; + totalDens.dPres += ( phaseFrac.dPres[ip] - value * phaseDens.dPres[ip] ) * densInv; + totalDens.dTemp += ( phaseFrac.dTemp[ip] - value * phaseDens.dTemp[ip] ) * densInv; + + for( localIndex jc = 0; jc < numComps; ++jc ) + { + totalDens.dComp[jc] += ( phaseFrac.dComp[ip][jc] - value * phaseDens.dComp[ip][jc] ) * densInv; + } + } + + // 5.2. Invert the previous quantity to get actual density + totalDens.value = 1.0 / totalDens.value; + real64 const minusDens2 = -totalDens.value * totalDens.value; + totalDens.dPres *= minusDens2; + totalDens.dTemp *= minusDens2; + + for( localIndex jc = 0; jc < numComps; ++jc ) + { + totalDens.dComp[jc] *= minusDens2; + } + } +} + +} //namespace constitutive + +} //namespace geosx + +#endif //GEOSX_CONSTITUTIVE_FLUID_NEWMULTIPHASEMULTICOMPONENTFLUID_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.cpp new file mode 100644 index 00000000000..4446561b470 --- /dev/null +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.cpp @@ -0,0 +1,173 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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 Total, S.A + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file BrineCO2Density.cpp + */ + +#include "constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.hpp" + +#include "managers/Functions/FunctionManager.hpp" +#include "managers/GeosxState.hpp" + +namespace geosx +{ + +using namespace stringutilities; + +namespace PVTProps +{ + +BrineCO2Density::BrineCO2Density( array1d< string > const & inputPara, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ): + PVTFunctionBase( inputPara[1], + componentNames, + componentMolarWeight ) +{ + bool notFound = 1; + for( localIndex i = 0; i < componentNames.size(); ++i ) + { + if( componentNames[i] == "CO2" || componentNames[i] == "co2" ) + { + m_CO2Index = i; + notFound = 0; + break; + } + } + GEOSX_ERROR_IF( notFound, "Component CO2 is not found!" ); + + notFound = 1; + for( localIndex i = 0; i < componentNames.size(); ++i ) + { + if( componentNames[i] == "Water" || componentNames[i] == "water" ) + { + m_waterIndex = i; + notFound = 0; + break; + } + } + GEOSX_ERROR_IF( notFound, "Component Water/Brine is not found!" ); + + makeTable( inputPara ); +} + +void BrineCO2Density::makeTable( array1d< string > const & inputPara ) +{ + array1d< array1d< real64 > > coordinates; + coordinates.resize( 2 ); + + real64 TStart = -1.0; + real64 TEnd = -1.0; + real64 dT = -1.0; + real64 PStart = -1.0; + real64 PEnd = -1.0; + real64 dP = -1.0; + real64 salinity = 0.0; + + GEOSX_ERROR_IF( inputPara.size() < 9, "Invalid BrineCO2Density input!" ); + + try + { + PStart = stod( inputPara[2] ); + PEnd = stod( inputPara[3] ); + dP = stod( inputPara[4] ); + + TStart = stod( inputPara[5] ); + TEnd = stod( inputPara[6] ); + dT = stod( inputPara[7] ); + + salinity = stod( inputPara[8] ); + } + catch( const std::invalid_argument & e ) + { + GEOSX_ERROR( "Invalid BrineCO2Density argument:" + string( e.what()) ); + } + + real64 P = PStart; + while( P <= PEnd ) + { + coordinates[0].emplace_back( P ); + P += dP; + } + + real64 T = TStart; + while( T <= TEnd ) + { + coordinates[1].emplace_back( T ); + T += dT; + } + + localIndex const nP = coordinates[0].size(); + localIndex const nT = coordinates[1].size(); + + array1d< real64 > values( nP * nT ); + calculateBrineDensity( coordinates, salinity, values ); + + FunctionManager * functionManager = &getGlobalState().getFunctionManager(); + m_brineDensityTable = functionManager->createChild( "TableFunction", "brineDensityTable" )->groupCast< TableFunction * >(); + m_brineDensityTable->setTableCoordinates( coordinates ); + m_brineDensityTable->setTableValues( values ); + m_brineDensityTable->reInitializeFunction(); + m_brineDensityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); +} + +void BrineCO2Density::calculateBrineDensity( array1d< array1d< real64 > > const & coordinates, + real64 const & salinity, + array1d< real64 > const & values ) +{ + constexpr real64 c1 = -9.9595; + constexpr real64 c2 = 7.0845; + constexpr real64 c3 = 3.9093; + + constexpr real64 a1 = -0.004539; + constexpr real64 a2 = -0.0001638; + constexpr real64 a3 = 0.00002551; + + constexpr real64 AA = -3.033405; + constexpr real64 BB = 10.128163; + constexpr real64 CC = -8.750567; + constexpr real64 DD = 2.663107; + + localIndex const numPressures = coordinates[0].size(); + localIndex const numTemperatures = coordinates[1].size(); + + for( localIndex i = 0; i < numPressures; ++i ) + { + real64 const P = coordinates[0][i] / 1e5; + + for( localIndex j = 0; j < numTemperatures; ++j ) + { + real64 const x = c1 * exp( a1 * salinity ) + + c2 * exp( a2 * coordinates[1][j] ) + + c3 * exp( a3 * P ); + values[j*numPressures+i] = (AA + BB * x + CC * x * x + DD * x * x * x) * 1000.0; + } + } +} + +BrineCO2Density::KernelWrapper BrineCO2Density::createKernelWrapper() +{ + return KernelWrapper( m_componentNames, + m_componentMolarWeight, + m_brineDensityTable, + m_CO2Index, + m_waterIndex ); +} + +REGISTER_CATALOG_ENTRY( PVTFunctionBase, BrineCO2Density, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) + +} // namespace PVTProps + +} // namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.hpp new file mode 100644 index 00000000000..48f0c80b246 --- /dev/null +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.hpp @@ -0,0 +1,226 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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 Total, S.A + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file BrineCO2Density.hpp + */ + +#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINECO2DENSITY_HPP_ +#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINECO2DENSITY_HPP_ + +#include "NewPVTFunctionBase.hpp" + +#include "managers/Functions/TableFunction.hpp" + +namespace geosx +{ + +namespace PVTProps +{ + +class BrineCO2DensityUpdate final : public PVTFunctionBaseUpdate +{ +public: + + BrineCO2DensityUpdate( arrayView1d< string const > const & componentNames, + arrayView1d< real64 const > const & componentMolarWeight, + TableFunction * brineDensityTable, + localIndex const CO2Index, + localIndex const waterIndex ) + : PVTFunctionBaseUpdate( componentNames, + componentMolarWeight ), + m_brineDensityTable( brineDensityTable->createKernelWrapper() ), + m_CO2Index( CO2Index ), + m_waterIndex( waterIndex ) + {} + + /// Default copy constructor + BrineCO2DensityUpdate( BrineCO2DensityUpdate const & ) = default; + + /// Default move constructor + BrineCO2DensityUpdate( BrineCO2DensityUpdate && ) = default; + + /// Deleted copy assignment operator + BrineCO2DensityUpdate & operator=( BrineCO2DensityUpdate const & ) = delete; + + /// Deleted move assignment operator + BrineCO2DensityUpdate & operator=( BrineCO2DensityUpdate && ) = delete; + + GEOSX_HOST_DEVICE + GEOSX_FORCE_INLINE + virtual void compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & phaseComposition, + real64 & value, + real64 & dValue_dPressure, + real64 & dValue_dTemperature, + arraySlice1d< real64 > const & dValue_dPhaseComposition, + bool useMass = 0 ) const override; + +protected: + + /// Table with brine density tabulated as a function (P,T,sal) + TableFunction::KernelWrapper const m_brineDensityTable; + + /// Index of the CO2 component + localIndex const m_CO2Index; + + /// Index of the water component + localIndex const m_waterIndex; + +}; + +class BrineCO2Density : public PVTFunctionBase +{ +public: + + BrineCO2Density( array1d< string > const & inputPara, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ); + + ~BrineCO2Density() override {} + + static string catalogName() { return "NewBrineCO2Density"; } + + virtual string getCatalogName() const override final { return catalogName(); } + + virtual PVTFunctionType functionType() const override + { + return PVTFunctionType::DENSITY; + } + + /// Type of kernel wrapper for in-kernel update + using KernelWrapper = BrineCO2DensityUpdate; + + /** + * @brief Create an update kernel wrapper. + * @return the wrapper + */ + KernelWrapper createKernelWrapper(); + + +private: + + void makeTable( array1d< string > const & inputPara ); + + void calculateBrineDensity( array1d< array1d< real64 > > const & coordinates, + real64 const & salinity, + array1d< real64 > const & values ); + + /// Table with brine density tabulated as a function of (P,T,sal) + TableFunction * m_brineDensityTable; + + /// Index of the CO2 phase + localIndex m_CO2Index; + + /// Index of the water phase + localIndex m_waterIndex; + +}; + +GEOSX_HOST_DEVICE +GEOSX_FORCE_INLINE +void BrineCO2DensityUpdate::compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & phaseComposition, + real64 & value, + real64 & dValue_dPressure, + real64 & dValue_dTemperature, + arraySlice1d< real64 > const & dValue_dPhaseComposition, + bool useMass ) const +{ + constexpr real64 a = 37.51; + constexpr real64 b = -9.585e-2; + constexpr real64 c = 8.740e-4; + constexpr real64 d = -5.044e-7; + + real64 const input[2] = { pressure, temperature }; + real64 density = 0.0; + real64 densityDeriv[2]{}; + m_brineDensityTable.compute( input, density, densityDeriv ); + + real64 const squaredTemp = temperature * temperature; + real64 const V = ( a + + b * temperature + + c * squaredTemp + + d * squaredTemp * temperature ) * 1e-6; + real64 const dV_dTemp = ( b + + 2 * c * temperature + + 3 * d * squaredTemp ) * 1e-6; + + // CO2 concentration + // C = X * den / (waterMW * (1.0 - X)); + real64 const denom = ( m_componentMolarWeight[m_waterIndex] * ( 1.0 - phaseComposition[m_CO2Index] ) ); + real64 const coef = phaseComposition[m_CO2Index] / denom; + real64 dCoef_dComp[2]{}; + dCoef_dComp[m_CO2Index] = 1.0 / denom; + dCoef_dComp[m_waterIndex] = -m_componentMolarWeight[m_waterIndex] * phaseComposition[m_CO2Index] / (denom * denom); + + real64 const conc = coef * density; + real64 const dConc_dPres = coef * densityDeriv[0]; + real64 const dConc_dTemp = coef * densityDeriv[1]; + real64 dConc_dComp[2]{}; + dConc_dComp[m_CO2Index] = dCoef_dComp[m_CO2Index] * density; + dConc_dComp[m_waterIndex] = dCoef_dComp[m_waterIndex] * density; + + // CO2 concentration times density times vol + real64 const concDensVol = conc * density * V; + real64 const dConcDensVol_dPres = ( dConc_dPres * density + conc * densityDeriv[0] ) * V; + real64 const dConcDensVol_dTemp = ( dConc_dTemp * density + conc * densityDeriv[1] ) * V + + conc * density * dV_dTemp; + real64 dConcDensVol_dComp[2]{}; + dConcDensVol_dComp[m_CO2Index] = dConc_dComp[m_CO2Index] * density * V; + dConcDensVol_dComp[m_waterIndex] = dConc_dComp[m_waterIndex] * density * V; + + // Brine density + // value = den + CO2MW * C - C * den * V; + if( useMass ) + { + value = density + + m_componentMolarWeight[m_CO2Index] * conc + - concDensVol; + dValue_dPressure = densityDeriv[0] + + m_componentMolarWeight[m_CO2Index] * dConc_dPres + - dConcDensVol_dPres; + dValue_dTemperature = densityDeriv[1] + + m_componentMolarWeight[m_CO2Index] * dConc_dTemp + - dConcDensVol_dTemp; + dValue_dPhaseComposition[m_CO2Index] = m_componentMolarWeight[m_CO2Index] * dConc_dComp[m_CO2Index] + - dConcDensVol_dComp[m_CO2Index]; + dValue_dPhaseComposition[m_waterIndex] = m_componentMolarWeight[m_CO2Index] * dConc_dComp[m_waterIndex] + - dConcDensVol_dComp[m_waterIndex]; + } + else // value = den / waterMW + C - C * den * V / waterMW; + { + value = density / m_componentMolarWeight[m_waterIndex] + + conc + - concDensVol / m_componentMolarWeight[m_waterIndex]; + dValue_dPressure = densityDeriv[0] / m_componentMolarWeight[m_waterIndex] + + dConc_dPres + - dConcDensVol_dPres / m_componentMolarWeight[m_waterIndex]; + dValue_dTemperature = densityDeriv[1] / m_componentMolarWeight[m_waterIndex] + + dConc_dTemp + - dConcDensVol_dTemp / m_componentMolarWeight[m_waterIndex]; + dValue_dPhaseComposition[m_CO2Index] = dConc_dComp[m_CO2Index] + - dConcDensVol_dComp[m_CO2Index] / m_componentMolarWeight[m_waterIndex]; + dValue_dPhaseComposition[m_waterIndex] = dConc_dComp[m_waterIndex] + - dConcDensVol_dComp[m_waterIndex] / m_componentMolarWeight[m_waterIndex]; + } +} + +} // end namespace PVTProps + +} // end namespace geosx + +#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINECO2DENSITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.cpp new file mode 100644 index 00000000000..ac146a3f5fa --- /dev/null +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.cpp @@ -0,0 +1,78 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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 Total, S.A + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file BrineViscosity.cpp + */ + +#include "constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.hpp" + +namespace geosx +{ + +using namespace stringutilities; + +namespace PVTProps +{ + +BrineViscosity::BrineViscosity( array1d< string > const & inputPara, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ): + PVTFunctionBase( inputPara[1], + componentNames, + componentMolarWeight ) +{ + makeCoefficients( inputPara ); +} + +void BrineViscosity::makeCoefficients( array1d< string > const & inputPara ) +{ + + constexpr real64 a = 0.0816; + constexpr real64 b = 0.0122; + constexpr real64 c = 0.000128; + constexpr real64 d = 0.000629; + constexpr real64 k = -0.7; + constexpr real64 waterVisc = 8.9e-4; //at 25C + + real64 m = -1.0; + + GEOSX_ERROR_IF( inputPara.size() < 3, "Invalid BrineViscosity input!" ); + + try + { + m = stod( inputPara[2] ); + } + catch( const std::invalid_argument & e ) + { + GEOSX_ERROR( "Invalid BrineViscosity argument:" + string( e.what() ) ); + } + + m_coef0 = (1.0 + a * m + b * m * m + c * m * m * m) * waterVisc; + m_coef1 = d * (1.0 - exp( k * m )) * waterVisc; +} + +BrineViscosity::KernelWrapper BrineViscosity::createKernelWrapper() +{ + return KernelWrapper( m_componentNames, + m_componentMolarWeight, + m_coef0, + m_coef1 ); +} + +REGISTER_CATALOG_ENTRY( PVTFunctionBase, BrineViscosity, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) + +} // end namespace PVTProps + +} // end namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.hpp new file mode 100644 index 00000000000..d6b2423e0b4 --- /dev/null +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.hpp @@ -0,0 +1,142 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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 Total, S.A + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file BrineViscosity.hpp + */ + +#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINEVISCOSITY_HPP_ +#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINEVISCOSITY_HPP_ + +#include "NewPVTFunctionBase.hpp" + +namespace geosx +{ + +namespace PVTProps +{ + +class BrineViscosityUpdate final : public PVTFunctionBaseUpdate +{ +public: + + BrineViscosityUpdate( arrayView1d< string const > const & componentNames, + arrayView1d< real64 const > const & componentMolarWeight, + real64 const & coef0, + real64 const & coef1 ) + : PVTFunctionBaseUpdate( componentNames, + componentMolarWeight ), + m_coef0( coef0 ), + m_coef1( coef1 ) + {} + + /// Default copy constructor + BrineViscosityUpdate( BrineViscosityUpdate const & ) = default; + + /// Default move constructor + BrineViscosityUpdate( BrineViscosityUpdate && ) = default; + + /// Deleted copy assignment operator + BrineViscosityUpdate & operator=( BrineViscosityUpdate const & ) = delete; + + /// Deleted move assignment operator + BrineViscosityUpdate & operator=( BrineViscosityUpdate && ) = delete; + + GEOSX_HOST_DEVICE + GEOSX_FORCE_INLINE + virtual void compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & phaseComposition, + real64 & value, + real64 & dValue_dPressure, + real64 & dValue_dTemperature, + arraySlice1d< real64 > const & dValue_dPhaseComposition, + bool useMass = 0 ) const override; + +protected: + + real64 const m_coef0; + + real64 const m_coef1; + +}; + + +class BrineViscosity : public PVTFunctionBase +{ +public: + + BrineViscosity( array1d< string > const & inputPara, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ); + + ~BrineViscosity() override {} + + static string catalogName() { return "NewBrineViscosity"; } + + virtual string getCatalogName() const override final { return catalogName(); } + + virtual PVTFunctionType functionType() const override + { + return PVTFunctionType::VISCOSITY; + } + + /// Type of kernel wrapper for in-kernel update + using KernelWrapper = BrineViscosityUpdate; + + /** + * @brief Create an update kernel wrapper. + * @return the wrapper + */ + KernelWrapper createKernelWrapper(); + +private: + + void makeCoefficients( array1d< string > const & inputPara ); + + real64 m_coef0; + + real64 m_coef1; + +}; + +GEOSX_HOST_DEVICE +GEOSX_FORCE_INLINE +void BrineViscosityUpdate::compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & phaseComposition, + real64 & value, + real64 & dValue_dPressure, + real64 & dValue_dTemperature, + arraySlice1d< real64 > const & dValue_dPhaseComposition, + bool useMass ) const +{ + GEOSX_UNUSED_VAR( pressure ); + GEOSX_UNUSED_VAR( phaseComposition ); + GEOSX_UNUSED_VAR( useMass ); + + value = m_coef0 + m_coef1 * temperature; + dValue_dPressure = 0.0; + dValue_dTemperature = m_coef1; + for( real64 & val : dValue_dPhaseComposition ) + { + val = 0.0; + } +} + +} // end namespace PVTProps + +} // end namespace geosx + +#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINEVISCOSITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.cpp new file mode 100644 index 00000000000..0da2118264d --- /dev/null +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.cpp @@ -0,0 +1,321 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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 Total, S.A + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file CO2Solubility.cpp + */ + +#include "constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.hpp" + +#include "managers/Functions/FunctionManager.hpp" +#include "managers/GeosxState.hpp" + +namespace geosx +{ + +using namespace stringutilities; + + +namespace PVTProps +{ + +constexpr real64 T_K_f = 273.15; +constexpr real64 P_Pa_f = 1e+5; +constexpr real64 P_c = 73.773 * P_Pa_f; +constexpr real64 T_c = 304.1282; +constexpr real64 Rgas = 8.314467; +constexpr real64 V_c = Rgas*T_c/P_c; + +constexpr real64 acoef[] = +{ 8.99288497e-2, -4.94783127e-1, 4.77922245e-2, 1.03808883e-2, -2.82516861e-2, 9.49887563e-2, 5.20600880e-4, + -2.93540971e-4, -1.77265112e-3, -2.51101973e-5, 8.93353441e-5, 7.88998563e-5, -1.66727022e-2, 1.398, 2.96e-2 }; + +namespace detail +{ + +real64 ff( real64 const & T, real64 const & P, real64 const & V_r ) +{ + real64 const P_r = P*P_Pa_f/P_c; + real64 const T_r = (T_K_f+T)/T_c; + + real64 const f_Z = 1.0 + + ( acoef[0] + acoef[1]/(T_r * T_r) + acoef[2]/(T_r * T_r * T_r) )/V_r + + ( acoef[3] + acoef[4]/(T_r * T_r) + acoef[5]/(T_r * T_r * T_r) )/(V_r*V_r) + + ( acoef[6] + acoef[7]/(T_r * T_r) + acoef[8]/(T_r * T_r * T_r) )/(V_r*V_r*V_r*V_r) + + ( acoef[9] + acoef[10]/(T_r * T_r) + acoef[11]/(T_r * T_r * T_r) )/(V_r*V_r*V_r*V_r*V_r) + + acoef[12]/(T_r * T_r * T_r)/(V_r * V_r) * (acoef[13] + acoef[14]/(V_r * V_r)) * exp( -acoef[14]/(V_r * V_r)) - P_r * V_r / T_r; + + return f_Z; +} + +real64 PWater( real64 const & T ) +{ + constexpr real64 ccoef[] = { -38.640844, 5.8948420, 59.876516, 26.654627, 10.637097 }; + + real64 const P_c_w = 220.85; // H2O critical pressure (bars) + real64 const T_c_w = 647.29; // H2O critical temperature (K) + real64 const tt = ( (T+T_K_f)-T_c_w )/T_c_w; + real64 const x = (P_c_w*(T+T_K_f)/T_c_w) + * (1 + ccoef[0]*pow( -tt, 1.9 ) + ccoef[1]*tt + ccoef[2]*tt*tt + ccoef[3]*tt*tt*tt + ccoef[4]*tt*tt*tt*tt); + + return x; +} + +real64 logF( real64 const & T, real64 const & P, real64 const & V_r ) +{ + real64 const P_r = P*P_Pa_f/P_c; + real64 const T_r = (T_K_f+T)/T_c; + real64 const Z = P_r * V_r/T_r; + + real64 const log_f = Z - 1 - log( Z ) + + ( acoef[0] + acoef[1]/T_r/T_r + acoef[2]/T_r/T_r/T_r )/V_r + + ( acoef[3] + acoef[4]/T_r/T_r + acoef[5]/T_r/T_r/T_r )/2.0/V_r/V_r + + ( acoef[6] + acoef[7]/T_r/T_r + acoef[8]/T_r/T_r/T_r )/4.0/V_r/V_r/V_r/V_r + + ( acoef[9] + acoef[10]/T_r/T_r + acoef[11]/T_r/T_r/T_r )/5.0/V_r/V_r/V_r/V_r/V_r + + acoef[12]/2.0/T_r/T_r/T_r/acoef[14] * ( acoef[13] + 1.0 - (acoef[13] + 1.0 + acoef[14]/V_r/V_r) * exp( -acoef[14]/V_r/V_r ) ); + + return log_f; +} + +real64 Par( real64 const & T, real64 const & P, real64 const * cc ) +{ + real64 x = cc[0] + + cc[1]*T + + cc[2]/T + + cc[3]*T*T + + cc[4]/(630.0-T) + + cc[5]*P + + cc[6]*P *log( T ) + + cc[7]*P/T + + cc[8]*P/(630.0-T) + + cc[9]*P*P/(630.0-T)/(630.0-T) + + cc[10]*T *log( P ); + + return x; +} + +}; + +CO2Solubility::CO2Solubility( array1d< string > const & inputPara, + array1d< string > const & phaseNames, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ): + FlashModelBase( inputPara[1], + componentNames, + componentMolarWeight ) +{ + GEOSX_ERROR_IF( phaseNames.size() != 2, "The CO2Solubility model is a two-phase model" ); + GEOSX_ERROR_IF( componentNames.size() != 2, "The CO2Solubility model is a two-component model" ); + + bool notFound = 1; + for( localIndex i = 0; i < componentNames.size(); ++i ) + { + if( componentNames[i] == "CO2" || componentNames[i] == "co2" ) + { + m_CO2Index = i; + notFound = 0; + break; + } + } + GEOSX_ERROR_IF( notFound, "Component CO2 is not found!" ); + + notFound = 1; + for( localIndex i = 0; i < componentNames.size(); ++i ) + { + if( componentNames[i] == "Water" || componentNames[i] == "water" ) + { + m_waterIndex = i; + notFound = 0; + break; + } + } + GEOSX_ERROR_IF( notFound, "Component Water/Brine is not found!" ); + + notFound = 1; + for( localIndex i = 0; i < phaseNames.size(); ++i ) + { + if( phaseNames[i] == "CO2" || phaseNames[i] == "co2" || + phaseNames[i] == "gas" || phaseNames[i] == "Gas" ) + { + m_phaseGasIndex = i; + notFound = 0; + break; + } + } + GEOSX_ERROR_IF( notFound, "Phase co2/gas is not found!" ); + + notFound = 1; + for( localIndex i = 0; i < phaseNames.size(); ++i ) + { + if( streq( phaseNames[i], "Water" ) || streq( phaseNames[i], "water" ) || + streq( phaseNames[i], "Liquid" ) || streq( phaseNames[i], "liquid" ) ) + { + m_phaseLiquidIndex = i; + notFound = 0; + break; + } + } + GEOSX_ERROR_IF( notFound, "Phase water/liquid is not found!" ); + + makeTable( inputPara ); +} + +void CO2Solubility::makeTable( array1d< string > const & inputPara ) +{ + array1d< array1d< real64 > > coordinates; + coordinates.resize( 2 ); + + real64 TStart = -1.0; + real64 TEnd = -1.0; + real64 dT = -1.0; + real64 PStart = -1.0; + real64 PEnd = -1.0; + real64 dP = -1.0; + real64 salinity = 0; + + GEOSX_ERROR_IF( inputPara.size() < 9, "Invalid CO2Solubility input!" ); + + try + { + PStart = stod( inputPara[2] ); + PEnd = stod( inputPara[3] ); + dP = stod( inputPara[4] ); + + TStart = stod( inputPara[5] ); + TEnd = stod( inputPara[6] ); + dT = stod( inputPara[7] ); + + salinity = stod( inputPara[8] ); + } + catch( const std::invalid_argument & e ) + { + GEOSX_ERROR( "Invalid CO2Solubility argument:" + string( e.what()) ); + } + + real64 P = PStart; + while( P <= PEnd ) + { + coordinates[0].emplace_back( P ); + P += dP; + } + + real64 T = TStart; + while( T <= TEnd ) + { + coordinates[1].emplace_back( T ); + T += dT; + } + + localIndex const nP = coordinates[0].size(); + localIndex const nT = coordinates[1].size(); + array1d< real64 > values( nP * nT ); + calculateCO2Solubility( coordinates, salinity, values ); + + FunctionManager * functionManager = &getGlobalState().getFunctionManager(); + m_CO2SolubilityTable = functionManager->createChild( "TableFunction", "CO2SolubilityTable" )->groupCast< TableFunction * >(); + m_CO2SolubilityTable->setTableCoordinates( coordinates ); + m_CO2SolubilityTable->setTableValues( values ); + m_CO2SolubilityTable->reInitializeFunction(); + m_CO2SolubilityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); +} + +void CO2Solubility::calculateCO2Solubility( array1d< array1d< real64 > > const & coordinates, + real64 const & salinity, + array1d< real64 > const & values ) +{ + constexpr real64 mu[] = + { 28.9447706, -0.0354581768, -4770.67077, 1.02782768e-5, 33.8126098, 9.04037140e-3, + -1.14934031e-3, -0.307405726, -0.0907301486, 9.32713393e-4, 0 }; + constexpr real64 lambda[] = { -0.411370585, 6.07632013e-4, 97.5347708, 0, 0, 0, 0, -0.0237622469, 0.0170656236, 0, 1.41335834e-5 }; + constexpr real64 zeta[] = { 3.36389723e-4, -1.98298980e-5, 0, 0, 0, 0, 0, 2.12220830e-3, -5.24873303e-3, 0, 0 }; + + localIndex const numPressures = coordinates[0].size(); + localIndex const numTemperatures = coordinates[1].size(); + + for( localIndex i = 0; i < numPressures; ++i ) + { + real64 const P = coordinates[0][i] / P_Pa_f; + + for( localIndex j = 0; j < numTemperatures; ++j ) + { + real64 const T = coordinates[1][j]; + + real64 V_r = 0.0; + CO2SolubilityFunction( T, P, V_r, &detail::ff ); + + real64 const logK = detail::Par( T+T_K_f, P, mu ) + - detail::logF( T, P, V_r ) + + 2*detail::Par( T+T_K_f, P, lambda ) * salinity + + detail::Par( T+T_K_f, P, zeta ) * salinity * salinity; + + real64 const y_CO2 = (P - detail::PWater( T ))/P; + values[j*numPressures+i] = y_CO2 * P / exp( logK ); + } + } +} + +void CO2Solubility::CO2SolubilityFunction( real64 const & T, + real64 const & P, + real64 & V_r, + real64 (*f)( real64 const & x1, real64 const & x2, real64 const & x3 ) ) +{ + + constexpr real64 eps = 1e-9; + constexpr real64 dx = 1e-10; + int count = 0; + real64 Vr_int = 0.05; + + V_r = 0.75*Rgas*(T_K_f+T)/(P*P_Pa_f)*(1/V_c); + + for(;; ) + { + if( V_r < 0.0 ) + { + V_r = Vr_int; + Vr_int += 0.05; + } + + real64 const v0 = (*f)( T, P, V_r ); + real64 const v1 = (*f)( T, P, V_r+dx ); + real64 const dre = -v0/((v1-v0)/dx); + + if( fabs( dre ) < eps ) + { + break; + } + + GEOSX_ERROR_IF( count > 50, "CO2Solubility NR convergence fails! " << "dre = " << dre << ", eps = " << eps ); + + count++; + V_r += dre; + } +} + + +CO2Solubility::KernelWrapper CO2Solubility::createKernelWrapper() +{ + return KernelWrapper( m_componentNames, + m_componentMolarWeight, + m_CO2SolubilityTable, + m_CO2Index, + m_waterIndex, + m_phaseGasIndex, + m_phaseLiquidIndex ); +} + +REGISTER_CATALOG_ENTRY( FlashModelBase, CO2Solubility, array1d< string > const &, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) + +} // end namespace PVTProps + +} // end namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.hpp new file mode 100644 index 00000000000..8a912bc69d4 --- /dev/null +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.hpp @@ -0,0 +1,298 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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 Total, S.A + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file CO2Solubility.hpp + */ + +#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_CO2SOLUBILITY_HPP_ +#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_CO2SOLUBILITY_HPP_ + +#include "NewFlashModelBase.hpp" + +#include "managers/Functions/TableFunction.hpp" + +namespace geosx +{ + +namespace PVTProps +{ + +constexpr real64 minForDivision = 1e-10; + +class CO2SolubilityUpdate final : public FlashModelBaseUpdate +{ +public: + + CO2SolubilityUpdate( arrayView1d< string const > const & componentNames, + arrayView1d< real64 const > const & componentMolarWeight, + TableFunction * CO2SolubilityTable, + localIndex const CO2Index, + localIndex const waterIndex, + localIndex const phaseGasIndex, + localIndex const phaseLiquidIndex ) + : FlashModelBaseUpdate( componentNames, + componentMolarWeight ), + m_CO2SolubilityTable( CO2SolubilityTable->createKernelWrapper() ), + m_CO2Index( CO2Index ), + m_waterIndex( waterIndex ), + m_phaseGasIndex( phaseGasIndex ), + m_phaseLiquidIndex( phaseLiquidIndex ) + {} + + /// Default copy constructor + CO2SolubilityUpdate( CO2SolubilityUpdate const & ) = default; + + /// Default move constructor + CO2SolubilityUpdate( CO2SolubilityUpdate && ) = default; + + /// Deleted copy assignment operator + CO2SolubilityUpdate & operator=( CO2SolubilityUpdate const & ) = delete; + + /// Deleted move assignment operator + CO2SolubilityUpdate & operator=( CO2SolubilityUpdate && ) = delete; + + GEOSX_HOST_DEVICE + GEOSX_FORCE_INLINE + virtual void compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & compFraction, + arraySlice1d< real64 > const & phaseFraction, + arraySlice1d< real64 > const & dPhaseFraction_dPressure, + arraySlice1d< real64 > const & dPhaseFraction_dTemperature, + arraySlice2d< real64 > const & dPhaseFraction_dCompFraction, + arraySlice2d< real64 > const & phaseCompFraction, + arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, + arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, + arraySlice3d< real64 > const & dPhaseCompFraction_dCompFraction ) const; + +protected: + + /// Table with CO2 solubility tabulated as a function (P,T) + TableFunction::KernelWrapper const m_CO2SolubilityTable; + + /// Index of the CO2 phase + localIndex const m_CO2Index; + + /// Index of the water phase + localIndex const m_waterIndex; + + /// Index of the gas phase + localIndex const m_phaseGasIndex; + + /// Index of the liquid phase + localIndex const m_phaseLiquidIndex; + +}; + +class CO2Solubility : public FlashModelBase +{ +public: + + CO2Solubility( array1d< string > const & inputPara, + array1d< string > const & phaseNames, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ); + + ~CO2Solubility() override {} + + static string catalogName() { return "NewCO2Solubility"; } + + virtual string getCatalogName() const override final { return catalogName(); } + + /// Type of kernel wrapper for in-kernel update + using KernelWrapper = CO2SolubilityUpdate; + + /** + * @brief Create an update kernel wrapper. + * @return the wrapper + */ + KernelWrapper createKernelWrapper(); + +private: + + void makeTable( array1d< string > const & inputPara ); + + void calculateCO2Solubility( array1d< array1d< real64 > > const & coordinates, + real64 const & salinity, + array1d< real64 > const & values ); + + void CO2SolubilityFunction( real64 const & T, + real64 const & P, + real64 & V_r, + real64 (*f)( real64 const & x1, real64 const & x2, real64 const & x3 ) ); + + /// Table to compute solubility as a function of pressure and temperature + TableFunction * m_CO2SolubilityTable; + + /// Index of the CO2 component + localIndex m_CO2Index; + + /// Index of the water component + localIndex m_waterIndex; + + /// Index of the gas phase + localIndex m_phaseGasIndex; + + /// Index of the liquid phase + localIndex m_phaseLiquidIndex; +}; + +GEOSX_HOST_DEVICE +GEOSX_FORCE_INLINE +void CO2SolubilityUpdate::compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & compFraction, + arraySlice1d< real64 > const & phaseFraction, + arraySlice1d< real64 > const & dPhaseFraction_dPressure, + arraySlice1d< real64 > const & dPhaseFraction_dTemperature, + arraySlice2d< real64 > const & dPhaseFraction_dCompFraction, + arraySlice2d< real64 > const & phaseCompFraction, + arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, + arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, + arraySlice3d< real64 > const & dPhaseCompFraction_dCompFraction ) const +{ + // solubility mol/kg(water) X = Csat/W + real64 const input[2] = { pressure, temperature }; + real64 solubility = 0.0; + real64 solubilityDeriv[2]{}; + m_CO2SolubilityTable.compute( input, solubility, solubilityDeriv ); + + solubility *= m_componentMolarWeight[m_waterIndex]; + for( localIndex i = 0; i < 2; ++i ) + { + solubilityDeriv[i] *= m_componentMolarWeight[m_waterIndex]; + } + + real64 Y = 0.0; + real64 dY_dCompFrac[2]{}; + + // Y = C/W = z/(1-z) + + if( compFraction[m_CO2Index] > 1.0 - minForDivision ) + { + Y = compFraction[m_CO2Index] / minForDivision; + dY_dCompFrac[m_CO2Index] = (1.0 - compFraction[m_CO2Index]) / minForDivision; + dY_dCompFrac[m_waterIndex] = -compFraction[m_CO2Index] / minForDivision; + } + else + { + real64 const oneMinusCompFracInv = 1.0 / (1.0 - compFraction[m_CO2Index]); + Y = compFraction[m_CO2Index] * oneMinusCompFracInv; + dY_dCompFrac[m_CO2Index] = 1.0 * oneMinusCompFracInv; + dY_dCompFrac[m_waterIndex] = -compFraction[m_CO2Index] * oneMinusCompFracInv * oneMinusCompFracInv; + } + + if( Y < solubility ) + { + // liquid phase only + + // 1) Compute phase fractions + + phaseFraction[m_phaseLiquidIndex] = 1.0; + phaseFraction[m_phaseGasIndex] = 0.0; + for( real64 & val : dPhaseFraction_dPressure ) + { + val = 0.0; + } + for( real64 & val : dPhaseFraction_dTemperature ) + { + val = 0.0; + } + for( real64 & val : dPhaseFraction_dCompFraction ) + { + val = 0.0; + } + + // 2) Compute phase component fractions + + for( localIndex ic = 0; ic < 2; ++ic ) + { + phaseCompFraction[m_phaseLiquidIndex][ic] = compFraction[ic]; + // the two following lines are not present in Yue's code, unclear if this will have some consequences + phaseCompFraction[m_phaseGasIndex][m_CO2Index] = 1.0; + phaseCompFraction[m_phaseGasIndex][m_waterIndex] = 0.0; + for( localIndex jc = 0; jc < 2; ++jc ) + { + dPhaseCompFraction_dCompFraction[m_phaseLiquidIndex][ic][jc] = + (ic == jc ) ? ( 1 - compFraction[ic] ) : -compFraction[ic]; + dPhaseCompFraction_dCompFraction[m_phaseGasIndex][ic][jc] = 0.0; + } + } + for( real64 & val : dPhaseCompFraction_dPressure ) + { + val = 0.0; + } + for( real64 & val : dPhaseCompFraction_dTemperature ) + { + val = 0.0; + } + + } + else + { + // two-phase flow + + // 1) Compute phase fractions + + // liquid phase fraction = (Csat + W) / (C + W) = (Csat/W + 1) / (C/W + 1) + real64 const onePlusYInv = 1.0 / ( 1.0 + Y ); + phaseFraction[m_phaseLiquidIndex] = (solubility + 1.0) * onePlusYInv; + dPhaseFraction_dPressure[m_phaseLiquidIndex] = solubilityDeriv[0] * onePlusYInv; + dPhaseFraction_dTemperature[m_phaseLiquidIndex] = solubilityDeriv[1] * onePlusYInv; + dPhaseFraction_dCompFraction[m_phaseLiquidIndex][m_CO2Index] = + -dY_dCompFrac[m_CO2Index] * phaseFraction[m_phaseLiquidIndex] * onePlusYInv; + dPhaseFraction_dCompFraction[m_phaseLiquidIndex][m_waterIndex] = + -dY_dCompFrac[m_waterIndex] * phaseFraction[m_phaseLiquidIndex] * onePlusYInv; + + phaseFraction[m_phaseGasIndex] = 1.0 - phaseFraction[m_phaseLiquidIndex]; + dPhaseFraction_dPressure[m_phaseGasIndex] = -dPhaseFraction_dPressure[m_phaseLiquidIndex]; + dPhaseFraction_dTemperature[m_phaseGasIndex] = -dPhaseFraction_dTemperature[m_phaseLiquidIndex]; + dPhaseFraction_dCompFraction[m_phaseGasIndex][m_CO2Index] = -dPhaseFraction_dCompFraction[m_phaseLiquidIndex][m_CO2Index]; + dPhaseFraction_dCompFraction[m_phaseGasIndex][m_waterIndex] = -dPhaseFraction_dCompFraction[m_phaseLiquidIndex][m_waterIndex]; + + // 2) Compute phase component fractions + + // liquid phase composition CO2 = Csat / (Csat + W) = (Csat/W) / (Csat/W + 1) + real64 const onePlusSolubilityInv = 1.0 / ( 1.0 + solubility ); + phaseCompFraction[m_phaseLiquidIndex][m_CO2Index] = solubility * onePlusSolubilityInv; + dPhaseCompFraction_dPressure[m_phaseLiquidIndex][m_CO2Index] = solubilityDeriv[0] * (onePlusSolubilityInv*onePlusSolubilityInv); + dPhaseCompFraction_dTemperature[m_phaseLiquidIndex][m_CO2Index] = solubilityDeriv[1] * (onePlusSolubilityInv*onePlusSolubilityInv); + + phaseCompFraction[m_phaseLiquidIndex][m_waterIndex] = 1.0 - phaseCompFraction[m_phaseLiquidIndex][m_CO2Index]; + dPhaseCompFraction_dPressure[m_phaseLiquidIndex][m_waterIndex] = -dPhaseCompFraction_dPressure[m_phaseLiquidIndex][m_CO2Index]; + dPhaseCompFraction_dTemperature[m_phaseLiquidIndex][m_waterIndex] = -dPhaseCompFraction_dTemperature[m_phaseLiquidIndex][m_CO2Index]; + + // gas phase composition CO2 = 1.0 + + phaseCompFraction[m_phaseGasIndex][m_CO2Index] = 1.0; + phaseCompFraction[m_phaseGasIndex][m_waterIndex] = 0.0; + dPhaseCompFraction_dPressure[m_phaseGasIndex][m_CO2Index] = 0.0; + dPhaseCompFraction_dPressure[m_phaseGasIndex][m_waterIndex] = 0.0; + dPhaseCompFraction_dTemperature[m_phaseGasIndex][m_CO2Index] = 0.0; + dPhaseCompFraction_dTemperature[m_phaseGasIndex][m_waterIndex] = 0.0; + + // phaseCompFraction does not depend on globalComponentFraction + for( real64 & val : dPhaseCompFraction_dCompFraction ) + { + val = 0.0; + } + } +} + +} // end namespace PVTProps + +} // end namespace geosx + +#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_CO2SOLUBILITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.cpp new file mode 100644 index 00000000000..79c819396bf --- /dev/null +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.cpp @@ -0,0 +1,157 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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 Total, S.A + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file FenghourCO2Viscosity.cpp + */ + +#include "constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.hpp" + +#include "constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.hpp" +#include "managers/Functions/FunctionManager.hpp" +#include "managers/GeosxState.hpp" + +namespace geosx +{ + +namespace PVTProps +{ + +FenghourCO2Viscosity::FenghourCO2Viscosity( array1d< string > const & inputPara, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ): + PVTFunctionBase( inputPara[1], + componentNames, + componentMolarWeight ) +{ + makeTable( inputPara ); +} + +void FenghourCO2Viscosity::makeTable( array1d< string > const & inputPara ) +{ + array1d< array1d< real64 > > coordinates; + coordinates.resize( 2 ); + + real64 TStart = -1.0; + real64 TEnd = -1.0; + real64 dT = -1.0; + real64 PStart = -1.0; + real64 PEnd = -1.0; + real64 dP = -1.0; + + GEOSX_ERROR_IF( inputPara.size() < 8, "Invalid FenghourCO2Viscosity input!" ); + + try + { + PStart = stod( inputPara[2] ); + PEnd = stod( inputPara[3] ); + dP = stod( inputPara[4] ); + + TStart = stod( inputPara[5] ); + TEnd = stod( inputPara[6] ); + dT = stod( inputPara[7] ); + } + catch( const std::invalid_argument & e ) + { + GEOSX_ERROR( "Invalid FenghourCO2Viscosity argument:" + string( e.what()) ); + } + + real64 P = PStart; + while( P <= PEnd ) + { + coordinates[0].emplace_back( P ); + P += dP; + } + + real64 T = TStart; + while( T <= TEnd ) + { + coordinates[1].emplace_back( T ); + T += dT; + } + + localIndex nP = coordinates[0].size(); + localIndex nT = coordinates[1].size(); + array1d< real64 > valuesDensity( nP * nT ); + array1d< real64 > valuesViscosity( nP * nT ); + SpanWagnerCO2Density::calculateCO2Density( coordinates, valuesDensity ); + calculateCO2Viscosity( coordinates, valuesDensity, valuesViscosity ); + + FunctionManager * functionManager = &getGlobalState().getFunctionManager(); + m_CO2ViscosityTable = functionManager->createChild( "TableFunction", "CO2ViscosityTable" )->groupCast< TableFunction * >(); + m_CO2ViscosityTable->setTableCoordinates( coordinates ); + m_CO2ViscosityTable->setTableValues( valuesViscosity ); + m_CO2ViscosityTable->reInitializeFunction(); + m_CO2ViscosityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); +} + +void FenghourCO2Viscosity::fenghourCO2ViscosityFunction( real64 const & temperatureCent, + real64 const & density, + real64 & viscosity ) +{ + constexpr real64 espar = 251.196; + constexpr real64 esparInv = 1.0 / espar; + constexpr real64 aa[5] = { 0.235156, -0.491266, 5.211155e-2, 5.347906e-2, -1.537102e-2 }; + constexpr real64 d11 = 0.4071119e-2; + constexpr real64 d21 = 0.7198037e-4; + constexpr real64 d64 = 0.2411697e-16; + constexpr real64 d81 = 0.2971072e-22; + constexpr real64 d82 = -0.1627888e-22; + constexpr real64 vcrit = 0.0; + + // temperature in Kelvin + real64 const temperatureKelvin = temperatureCent + 273.15; + // evaluate vlimit from eqns 3-5 + real64 const Tred = temperatureKelvin * esparInv; + real64 const x = log( Tred ); + real64 const lnGfun = aa[0] + x * (aa[1] + x * (aa[2] + x *(aa[3] + x * aa[4]))); + real64 const GfunInv = exp( -lnGfun ); + real64 const vlimit = 1.00697 * sqrt( temperatureKelvin ) * GfunInv; + + real64 const d2 = density * density; + real64 const vxcess = density * (d11 + density * (d21 + d2*d2*(d64 / (Tred*Tred*Tred) + d2*(d81 + d82/Tred)))); + + viscosity = 1e-6 * (vlimit + vxcess + vcrit); +} + +void FenghourCO2Viscosity::calculateCO2Viscosity( array1d< array1d< real64 > > const & coordinates, + array1d< real64 > const & valuesDensity, + array1d< real64 > const & valuesViscosity ) +{ + localIndex const numPressures = coordinates[0].size(); + localIndex const numTemperatures = coordinates[1].size(); + + for( localIndex i = 0; i < numPressures; ++i ) + { + for( localIndex j = 0; j < numTemperatures; ++j ) + { + fenghourCO2ViscosityFunction( coordinates[1][j], + valuesDensity[j*numPressures+i], + valuesViscosity[j*numPressures+i] ); + } + } +} + +FenghourCO2Viscosity::KernelWrapper FenghourCO2Viscosity::createKernelWrapper() +{ + return KernelWrapper( m_componentNames, + m_componentMolarWeight, + m_CO2ViscosityTable ); +} + +REGISTER_CATALOG_ENTRY( PVTFunctionBase, FenghourCO2Viscosity, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) + +} // end namespace PVTProps + +} // end namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.hpp new file mode 100644 index 00000000000..e6d1dc0da6f --- /dev/null +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.hpp @@ -0,0 +1,148 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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 Total, S.A + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file FenghourCO2Viscosity.hpp + */ + +#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FENGHOURCO2VISCOSITY_HPP_ +#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FENGHOURCO2VISCOSITY_HPP_ + +#include "NewPVTFunctionBase.hpp" + +#include "managers/Functions/TableFunction.hpp" + +namespace geosx +{ + +namespace PVTProps +{ + +class FenghourCO2ViscosityUpdate final : public PVTFunctionBaseUpdate +{ +public: + + FenghourCO2ViscosityUpdate( arrayView1d< string const > const & componentNames, + arrayView1d< real64 const > const & componentMolarWeight, + TableFunction * CO2ViscosityTable ) + : PVTFunctionBaseUpdate( componentNames, + componentMolarWeight ), + m_CO2ViscosityTable( CO2ViscosityTable->createKernelWrapper() ) + {} + + /// Default copy constructor + FenghourCO2ViscosityUpdate( FenghourCO2ViscosityUpdate const & ) = default; + + /// Default move constructor + FenghourCO2ViscosityUpdate( FenghourCO2ViscosityUpdate && ) = default; + + /// Deleted copy assignment operator + FenghourCO2ViscosityUpdate & operator=( FenghourCO2ViscosityUpdate const & ) = delete; + + /// Deleted move assignment operator + FenghourCO2ViscosityUpdate & operator=( FenghourCO2ViscosityUpdate && ) = delete; + + GEOSX_HOST_DEVICE + GEOSX_FORCE_INLINE + virtual void compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & phaseComposition, + real64 & value, + real64 & dValue_dPressure, + real64 & dValue_dTemperature, + arraySlice1d< real64 > const & dValue_dPhaseComposition, + bool useMass = 0 ) const override; + +protected: + + /// Table with viscosity tabulated as a function (P,T) + TableFunction::KernelWrapper const m_CO2ViscosityTable; + +}; + +class FenghourCO2Viscosity : public PVTFunctionBase +{ +public: + + FenghourCO2Viscosity( array1d< string > const & inputPara, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ); + ~FenghourCO2Viscosity() override {} + + static string catalogName() { return "NewFenghourCO2Viscosity"; } + + virtual string getCatalogName() const override final { return catalogName(); } + + virtual PVTFunctionType functionType() const override + { + return PVTFunctionType::VISCOSITY; + } + + /// Type of kernel wrapper for in-kernel update + using KernelWrapper = FenghourCO2ViscosityUpdate; + + /** + * @brief Create an update kernel wrapper. + * @return the wrapper + */ + KernelWrapper createKernelWrapper(); + +private: + + void makeTable( array1d< string > const & inputPara ); + + void calculateCO2Viscosity( array1d< array1d< real64 > > const & coordinates, + array1d< real64 > const & valuesDensity, + array1d< real64 > const & valuesViscosity ); + + void fenghourCO2ViscosityFunction( real64 const & temperatureCent, + real64 const & density, + real64 & viscosity ); + + /// Table with CO2 viscosity tabulated as a function of (P,T) + TableFunction * m_CO2ViscosityTable; + +}; + +GEOSX_HOST_DEVICE +GEOSX_FORCE_INLINE +void FenghourCO2ViscosityUpdate::compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & phaseComposition, + real64 & value, + real64 & dValue_dPressure, + real64 & dValue_dTemperature, + arraySlice1d< real64 > const & dValue_dPhaseComposition, + bool useMass ) const +{ + GEOSX_UNUSED_VAR( phaseComposition ); + GEOSX_UNUSED_VAR( useMass ); + + real64 const input[2] = { pressure, temperature }; + real64 densityDeriv[2]{}; + m_CO2ViscosityTable.compute( input, value, densityDeriv ); + dValue_dPressure = densityDeriv[0]; + dValue_dTemperature = densityDeriv[1]; + + for( real64 & val : dValue_dPhaseComposition ) + { + val = 0.0; + } +} + +} // end namespace PVTProps + +} // end namespace geosx + +#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FENGHOURCO2VISCOSITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewFlashModelBase.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewFlashModelBase.hpp new file mode 100644 index 00000000000..af4cc542074 --- /dev/null +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/NewFlashModelBase.hpp @@ -0,0 +1,124 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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 Total, S.A + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file FlashModelBase.hpp + */ + +#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWFLASHMODELBASE_HPP_ +#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWFLASHMODELBASE_HPP_ + +#include "codingUtilities/StringUtilities.hpp" +#include "dataRepository/ObjectCatalog.hpp" + +namespace geosx +{ + +namespace PVTProps +{ + +class FlashModelBaseUpdate +{ +public: + + FlashModelBaseUpdate( arrayView1d< string const > const & componentNames, + arrayView1d< real64 const > const & componentMolarWeight ) + : + m_componentNames( componentNames ), + m_componentMolarWeight( componentMolarWeight ) + {} + + /// Default copy constructor + FlashModelBaseUpdate( FlashModelBaseUpdate const & ) = default; + + /// Default move constructor + FlashModelBaseUpdate( FlashModelBaseUpdate && ) = default; + + /// Deleted copy assignment operator + FlashModelBaseUpdate & operator=( FlashModelBaseUpdate const & ) = delete; + + /// Deleted move assignment operator + FlashModelBaseUpdate & operator=( FlashModelBaseUpdate && ) = delete; + + GEOSX_HOST_DEVICE + GEOSX_FORCE_INLINE + virtual void compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & compFraction, + arraySlice1d< real64 > const & phaseFraction, + arraySlice1d< real64 > const & dPhaseFraction_dPressure, + arraySlice1d< real64 > const & dPhaseFraction_dTemperature, + arraySlice2d< real64 > const & dPhaseFraction_dCompFraction, + arraySlice2d< real64 > const & phaseCompFraction, + arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, + arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, + arraySlice3d< real64 > const & dPhaseCompFraction_dCompFraction ) const = 0; + +protected: + + /// Array storing the name of the components + arrayView1d< string const > m_componentNames; + + /// Array storing the component molar weights + arrayView1d< real64 const > m_componentMolarWeight; + +}; + + +class FlashModelBase +{ +public: + + FlashModelBase( string const & name, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ): + m_modelName( name ), + m_componentNames( componentNames ), + m_componentMolarWeight( componentMolarWeight ) + {} + + virtual ~FlashModelBase() {} + + using CatalogInterface = dataRepository::CatalogInterface< FlashModelBase, array1d< string > const &, + array1d< string > const &, + array1d< string > const &, + array1d< real64 > const & >; + static typename CatalogInterface::CatalogType & getCatalog() + { + static CatalogInterface::CatalogType catalog; + return catalog; + } + + virtual string getCatalogName() const = 0; + + string const & flashModelName() const { return m_modelName; } + +protected: + + /// Name the solubility model + string m_modelName; + + /// Array storing the name of the components + array1d< string > m_componentNames; + + /// Array storing the component molar weights + array1d< real64 > m_componentMolarWeight; + +}; + +} // end namespace PVTProps + +} // end namespace geosx + +#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWFLASHMODELBASE_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewPVTFunctionBase.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewPVTFunctionBase.hpp new file mode 100644 index 00000000000..789403a73a7 --- /dev/null +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/NewPVTFunctionBase.hpp @@ -0,0 +1,124 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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 Total, S.A + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file NewPVTFunctionBase.hpp + */ + +#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWPVTFUNCTIONBASE_HPP_ +#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWPVTFUNCTIONBASE_HPP_ + +#include "codingUtilities/StringUtilities.hpp" +#include "dataRepository/ObjectCatalog.hpp" + +namespace geosx +{ + +namespace PVTProps +{ + +enum class PVTFunctionType { UNKNOWN, DENSITY, VISCOSITY }; + +class PVTFunctionBaseUpdate +{ +public: + PVTFunctionBaseUpdate( arrayView1d< string const > const & componentNames, + arrayView1d< real64 const > const & componentMolarWeight ) + : + m_componentNames( componentNames ), + m_componentMolarWeight( componentMolarWeight ) + {} + + /// Default copy constructor + PVTFunctionBaseUpdate( PVTFunctionBaseUpdate const & ) = default; + + /// Default move constructor + PVTFunctionBaseUpdate( PVTFunctionBaseUpdate && ) = default; + + /// Deleted copy assignment operator + PVTFunctionBaseUpdate & operator=( PVTFunctionBaseUpdate const & ) = delete; + + /// Deleted move assignment operator + PVTFunctionBaseUpdate & operator=( PVTFunctionBaseUpdate && ) = delete; + + GEOSX_HOST_DEVICE + GEOSX_FORCE_INLINE + virtual void compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & phaseComposition, + real64 & value, + real64 & dValue_dPresure, + real64 & dValue_dTemperature, + arraySlice1d< real64 > const & dValue_dPhaseComposition, + bool useMass = 0 ) const = 0; + +protected: + + /// Array storing the name of the components + arrayView1d< string const > m_componentNames; + + /// Array storing the component molar weights + arrayView1d< real64 const > m_componentMolarWeight; + +}; + +class PVTFunctionBase +{ + +public: + + PVTFunctionBase( string const & name, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ) + : + m_functionName( name ), + m_componentNames( componentNames ), + m_componentMolarWeight( componentMolarWeight ) + {} + + virtual ~PVTFunctionBase() {} + + using CatalogInterface = dataRepository::CatalogInterface< PVTFunctionBase, array1d< string > const &, + array1d< string > const &, + array1d< real64 > const & >; + static typename CatalogInterface::CatalogType & getCatalog() + { + static CatalogInterface::CatalogType catalog; + return catalog; + } + + virtual string getCatalogName() const = 0; + + string const & functionName() const { return m_functionName; } + + virtual PVTFunctionType functionType() const = 0; + +protected: + + /// Name of the PVT function + string m_functionName; + + /// Array storing the name of the components + array1d< string > m_componentNames; + + /// Array storing the component molar weights + array1d< real64 > m_componentMolarWeight; + +}; + +} // end namespace PVTProps + +} // end namespace geosx + +#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWPVTFUNCTIONBASE_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.cpp new file mode 100644 index 00000000000..0d8704cbf14 --- /dev/null +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.cpp @@ -0,0 +1,316 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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 Total, S.A + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file SpanWagnerCO2Density.cpp + */ + +#include "constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.hpp" + +#include "managers/Functions/FunctionManager.hpp" +#include "managers/GeosxState.hpp" + +namespace geosx +{ + +using namespace stringutilities; + +namespace PVTProps +{ + +namespace detail +{ + +real64 f( real64 const & T, + real64 const & P, + real64 const & rho ) +{ + constexpr real64 n[] = + {0.38856823203161, 2.938547594274, -5.5867188534934, -0.76753199592477, 0.31729005580416, 0.54803315897767, 0.12279411220335, 2.165896154322, + 1.5841735109724, -0.23132705405503, 0.058116916431436, -0.55369137205382, 0.48946615909422, -0.024275739843501, 0.062494790501678, -0.12175860225246, + -0.37055685270086, -0.016775879700426, -0.11960736637987, -0.045619362508778, 0.035612789270346, -0.0074427727132052, -0.0017395704902432, + -0.021810121289527, 0.024332166559236, -0.037440133423463, 0.14338715756878, -0.13491969083286, -0.02315122505348, 0.012363125492901, 0.002105832197294, + -0.00033958519026368, 0.0055993651771592, -0.00030335118055646, -213.65488688320, 26641.569149272, -24027.212204557, -283.41603423999, 212.47284400179, + -0.66642276540751, 0.72608632349897, 0.055068668612842}; + + constexpr real64 d[] = {1, 1, 1, 1, 2, 2, 3, 1, 2, 4, 5, 5, 5, 6, 6, 6, 1, 1, 4, 4, 4, 7, 8, 2, 3, 3, 5, 5, 6, 7, 8, 10, 4, 8, 2, 2, 2, 3, 3}; + + constexpr real64 t[] = + {0, 0.75, 1, 2, 0.75, 2, 0.75, 1.5, 1.5, 2.5, 0, 1.5, 2, 0, 1, 2, 3, 6, 3, 6, 8, 6, 0, 7, 12, 16, 22, 24, 16, 24, 8, 2, 28, 14, 1, 0, 1, 3, 3}; + + constexpr real64 c[] = {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 6}; + + constexpr real64 alpha[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 15, 20}; + + constexpr real64 beta[] = + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 300, 300, 275, 275, 0.3, 0.3, 0.3}; + + constexpr real64 gamma0[] = + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.16, 1.19, 1.19, 1.25, 1.22}; + + constexpr real64 epslon[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1., 1., 1., 1., 1.}; + + constexpr real64 a[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.5, 3.5, 3.}; + + constexpr real64 b[] = + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.875, 0.925, 0.875}; + + constexpr real64 A[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.7, 0.7, 0.7}; + + constexpr real64 B[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.3, 0.3, 1.0}; + + constexpr real64 C[] = + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10.0, 10.0, 12.5}; + + constexpr real64 D[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 275, 275}; + + constexpr real64 T_c = 304.1282; + constexpr real64 rho_c = 467.6; + + constexpr real64 R = 188.9241; + + real64 tau = T_c / T; + real64 delta = rho / rho_c; + + real64 theta, Delta, Phi, dPhi_delta, dDelta_delta, dDelta_delta_b; + + real64 phi_r_delta = 0.0; + + for( int i=0; i<7; i++ ) + { + phi_r_delta += n[i] * d[i] * pow( delta, d[i]-1.0 ) * pow( tau, t[i] ); + } + + for( int i=7; i<34; i++ ) + { + phi_r_delta += n[i] * exp( -pow( delta, c[i] )) * pow( delta, d[i] - 1.0 ) * pow( tau, t[i] ) * (d[i] - c[i] * pow( delta, c[i] )); + } + + for( int i=34; i<39; i++ ) + { + phi_r_delta += n[i] * + pow( delta, + d[i] ) * + pow( tau, + t[i] ) * + exp( -alpha[i] * + pow( delta - epslon[i], 2.0 ) - beta[i] * pow( tau - gamma0[i], 2.0 )) * (d[i] / delta - 2.0 * alpha[i] * (delta - epslon[i])); + } + + for( int i=39; i<42; i++ ) + { + theta = 1.0 - tau + A[i] * pow( pow( delta - 1.0, 2.0 ), 1.0 / (2.0 * beta[i])); + Delta = pow( theta, 2.0 ) + B[i] * pow( pow( delta - 1.0, 2.0 ), a[i] ); + + Phi = exp( -C[i] * pow( delta - 1.0, 2.0 ) - D[i] * pow( tau - 1.0, 2.0 )); + + dPhi_delta = -2.0 * C[i] * (delta - 1.0) * Phi; + + dDelta_delta = (delta - 1.0) * + (A[i] * theta * 2.0 / beta[i] * + pow( pow( delta - 1.0, 2.0 ), 1.0 / (2.0 * beta[i]) - 1.0 ) + 2.0 * B[i] * a[i] * pow( pow( delta - 1.0, 2.0 ), a[i] - 1.0 )); + + dDelta_delta_b = b[i] * pow( Delta, b[i] - 1.0 ) * dDelta_delta; + + phi_r_delta += n[i] * (pow( Delta, b[i] ) * (Phi + delta *dPhi_delta) + dDelta_delta_b * delta * Phi); + } + + return rho * (1.0 + delta * phi_r_delta) / (P / (R * T)) - 1.0; +} + +}; + +SpanWagnerCO2Density::SpanWagnerCO2Density( array1d< string > const & inputPara, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ): + PVTFunctionBase( inputPara[1], + componentNames, + componentMolarWeight ) +{ + + bool notFound = 1; + for( localIndex i = 0; i < componentNames.size(); ++i ) + { + if( componentNames[i] == "CO2" || componentNames[i] == "co2" ) + { + m_CO2Index = i; + notFound = 0; + break; + } + } + GEOSX_ERROR_IF( notFound, "Component CO2 is not found!" ); + + makeTable( inputPara ); +} + +void SpanWagnerCO2Density::makeTable( array1d< string > const & inputPara ) +{ + array1d< array1d< real64 > > coordinates; + coordinates.resize( 2 ); + + real64 TStart = -1.0; + real64 TEnd = -1.0; + real64 dT = -1.0; + real64 PStart = -1.0; + real64 PEnd = -1.0; + real64 dP = -1.0; + + GEOSX_ERROR_IF( inputPara.size() < 8, "Invalid SpanWagnerCO2Density input!" ); + + try + { + PStart = stod( inputPara[2] ); + PEnd = stod( inputPara[3] ); + dP = stod( inputPara[4] ); + + TStart = stod( inputPara[5] ); + TEnd = stod( inputPara[6] ); + dT = stod( inputPara[7] ); + } + catch( const std::invalid_argument & e ) + { + GEOSX_ERROR( "Invalid SpanWagnerCO2Density argument:" + string( e.what()) ); + } + + real64 P = PStart; + while( P <= PEnd ) + { + coordinates[0].emplace_back( P ); + P += dP; + } + + real64 T = TStart; + while( T <= TEnd ) + { + coordinates[1].emplace_back( T ); + T += dT; + } + + localIndex const nP = coordinates[0].size(); + localIndex const nT = coordinates[1].size(); + array1d< real64 > values( nP * nT ); + calculateCO2Density( coordinates, values ); + + FunctionManager * functionManager = &getGlobalState().getFunctionManager(); + m_CO2DensityTable = functionManager->createChild( "TableFunction", "CO2DensityTable" )->groupCast< TableFunction * >(); + m_CO2DensityTable->setTableCoordinates( coordinates ); + m_CO2DensityTable->setTableValues( values ); + m_CO2DensityTable->reInitializeFunction(); + m_CO2DensityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); +} + + +void SpanWagnerCO2Density::calculateCO2Density( array1d< array1d< real64 > > const & coordinates, + array1d< real64 > const & values ) +{ + + constexpr real64 TK_f = 273.15; + + localIndex const numPressures = coordinates[0].size(); + localIndex const numTemperatures = coordinates[1].size(); + + for( localIndex i = 0; i < numPressures; ++i ) + { + real64 const PPa = coordinates[0][i]; + for( localIndex j = 0; j < numTemperatures; ++j ) + { + real64 const TK = coordinates[1][j] + TK_f; + spanWagnerCO2DensityFunction( TK, PPa, values[j*numPressures+i], &detail::f ); + } + } +} + +void SpanWagnerCO2Density::spanWagnerCO2DensityFunction( real64 const & T, + real64 const & P, + real64 & rho, + real64 (*f)( real64 const & x1, real64 const & x2, real64 const & x3 ) ) +{ + constexpr real64 P_Pa_f = 1e+5; + constexpr real64 P_c = 73.773 * P_Pa_f; + constexpr real64 T_c = 304.1282; + constexpr real64 rho_c = 467.6; + constexpr real64 R = 188.9241; + + constexpr real64 vpa[] = { -7.0602087, 1.9391218, -1.6463597, -3.2995634 }; + constexpr real64 vpt[] = { 1.0, 1.5, 2.0, 4.0 }; + + constexpr real64 lda[] = { 1.9245108, -0.62385555, -0.32731127, 0.39245142 }; + constexpr real64 ldt[] = { 0.340, 0.5, 1.6666666667, 1.833333333 }; + + real64 const eps = 1e-10; + real64 const dx = 1e-10; + int count = 0; + + // initial guess + if( T < T_c ) + { + real64 sum = 0; + for( int i=0; i < 4; i++ ) + { + sum += vpa[i] * pow( 1.0 - T / T_c, vpt[i] ); + } + real64 const psat = P_c * exp( T_c / T * sum ); + + sum = 0; + for( int i=0; i < 4; i++ ) + { + sum += lda[i] * pow( 1.0 - T / T_c, ldt[i] ); + } + real64 const denl = rho_c * exp( sum ); + + if( P >= psat ) + { + rho = denl; + } + else + { + rho = P / (R * T); + } + } + else + { + rho = 1.0 / (30.0 + R * T / P); + } + + // Newton loop + for(;; ) + { + real64 const v0 = (*f)( T, P, rho ); + real64 const v1 = (*f)( T, P, rho+dx ); + real64 const dre = -v0/((v1-v0)/dx); + if( fabs( dre ) < eps ) + { + break; + } + + GEOSX_ERROR_IF( count > 50, "SpanWagnerCO2Density NR convergence fails! " << "dre = " << dre << ", eps = " << eps ); + + count++; + rho += dre; + } +} + +SpanWagnerCO2Density::KernelWrapper SpanWagnerCO2Density::createKernelWrapper() +{ + return KernelWrapper( m_componentNames, + m_componentMolarWeight, + m_CO2DensityTable, + m_CO2Index ); +} + +REGISTER_CATALOG_ENTRY( PVTFunctionBase, SpanWagnerCO2Density, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) + +} // namespace PVTProps + +} // namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.hpp new file mode 100644 index 00000000000..c5aed105277 --- /dev/null +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.hpp @@ -0,0 +1,165 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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 Total, S.A + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file SpanWagnerCO2Density.hpp + */ + +#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_SPANWAGNERCO2DENSITY_HPP_ +#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_SPANWAGNERCO2DENSITY_HPP_ + +#include "NewPVTFunctionBase.hpp" + +#include "managers/Functions/TableFunction.hpp" + +namespace geosx +{ + +namespace PVTProps +{ + +class SpanWagnerCO2DensityUpdate final : public PVTFunctionBaseUpdate +{ +public: + + SpanWagnerCO2DensityUpdate( arrayView1d< string const > const & componentNames, + arrayView1d< real64 const > const & componentMolarWeight, + TableFunction * CO2DensityTable, + localIndex const CO2Index ) + : PVTFunctionBaseUpdate( componentNames, + componentMolarWeight ), + m_CO2DensityTable( CO2DensityTable->createKernelWrapper() ), + m_CO2Index( CO2Index ) + {} + + /// Default copy constructor + SpanWagnerCO2DensityUpdate( SpanWagnerCO2DensityUpdate const & ) = default; + + /// Default move constructor + SpanWagnerCO2DensityUpdate( SpanWagnerCO2DensityUpdate && ) = default; + + /// Deleted copy assignment operator + SpanWagnerCO2DensityUpdate & operator=( SpanWagnerCO2DensityUpdate const & ) = delete; + + /// Deleted move assignment operator + SpanWagnerCO2DensityUpdate & operator=( SpanWagnerCO2DensityUpdate && ) = delete; + + GEOSX_HOST_DEVICE + GEOSX_FORCE_INLINE + virtual void compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & phaseComposition, + real64 & value, + real64 & dValue_dPressure, + real64 & dValue_dTemperature, + arraySlice1d< real64 > const & dValue_dPhaseComposition, + bool useMass = 0 ) const override; + +protected: + + /// Table with brine density tabulated as a function (P,T,sal) + TableFunction::KernelWrapper const m_CO2DensityTable; + + /// Index of the CO2 component + localIndex const m_CO2Index; + +}; + +class SpanWagnerCO2Density : public PVTFunctionBase +{ +public: + + SpanWagnerCO2Density( array1d< string > const & inputPara, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ); + + ~SpanWagnerCO2Density() override {} + + static string catalogName() { return "NewSpanWagnerCO2Density"; } + + virtual string getCatalogName() const override final { return catalogName(); } + + virtual PVTFunctionType functionType() const override + { + return PVTFunctionType::DENSITY; + } + + /// Type of kernel wrapper for in-kernel update + using KernelWrapper = SpanWagnerCO2DensityUpdate; + + /** + * @brief Create an update kernel wrapper. + * @return the wrapper + */ + KernelWrapper createKernelWrapper(); + + static + void calculateCO2Density( array1d< array1d< real64 > > const & coordinates, + array1d< real64 > const & values ); + +private: + + void makeTable( array1d< string > const & inputPara ); + + static + void spanWagnerCO2DensityFunction( real64 const & T, + real64 const & P, + real64 & rho, + real64 (*f)( real64 const & x1, real64 const & x2, real64 const & x3 ) ); + + /// Table with CO2 density tabulated as a function of (P,T) + TableFunction * m_CO2DensityTable; + + /// Index of the CO2 component + localIndex m_CO2Index; + +}; + +GEOSX_HOST_DEVICE +GEOSX_FORCE_INLINE +void SpanWagnerCO2DensityUpdate::compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & phaseComposition, + real64 & value, + real64 & dValue_dPressure, + real64 & dValue_dTemperature, + arraySlice1d< real64 > const & dValue_dPhaseComposition, + bool useMass ) const +{ + GEOSX_UNUSED_VAR( phaseComposition ); + + real64 const input[2] = { pressure, temperature }; + real64 densityDeriv[2]{}; + m_CO2DensityTable.compute( input, value, densityDeriv ); + dValue_dPressure = densityDeriv[0]; + dValue_dTemperature = densityDeriv[1]; + + if( !useMass ) + { + value /= m_componentMolarWeight[m_CO2Index]; + dValue_dPressure /= m_componentMolarWeight[m_CO2Index]; + dValue_dTemperature /= m_componentMolarWeight[m_CO2Index]; + } + + for( real64 & val : dValue_dPhaseComposition ) + { + val = 0.0; + } +} + +} // end namespace PVTProps + +} // end namespace geosx + +#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_SPANWAGNERCO2DENSITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/multiFluidSelector.hpp b/src/coreComponents/constitutive/fluid/multiFluidSelector.hpp index 7b8ee2db83b..787d4a3ec94 100644 --- a/src/coreComponents/constitutive/fluid/multiFluidSelector.hpp +++ b/src/coreComponents/constitutive/fluid/multiFluidSelector.hpp @@ -22,6 +22,7 @@ #include "constitutive/fluid/CompositionalMultiphaseFluid.hpp" #include "constitutive/fluid/BlackOilFluid.hpp" #include "constitutive/fluid/MultiPhaseMultiComponentFluid.hpp" +#include "constitutive/fluid/NewMultiPhaseMultiComponentFluid.hpp" namespace geosx { @@ -35,7 +36,8 @@ void constitutiveUpdatePassThru( MultiFluidBase const & fluid, { ConstitutivePassThruHandler< BlackOilFluid, CompositionalMultiphaseFluid, - MultiPhaseMultiComponentFluid >::execute( fluid, std::forward< LAMBDA >( lambda ) ); + MultiPhaseMultiComponentFluid, + NewMultiPhaseMultiComponentFluid >::execute( fluid, std::forward< LAMBDA >( lambda ) ); } template< typename LAMBDA > @@ -44,7 +46,8 @@ void constitutiveUpdatePassThru( MultiFluidBase & fluid, { ConstitutivePassThruHandler< BlackOilFluid, CompositionalMultiphaseFluid, - MultiPhaseMultiComponentFluid >::execute( fluid, std::forward< LAMBDA >( lambda ) ); + MultiPhaseMultiComponentFluid, + NewMultiPhaseMultiComponentFluid >::execute( fluid, std::forward< LAMBDA >( lambda ) ); } } // namespace constitutive diff --git a/src/coreComponents/constitutive/unitTests/CMakeLists.txt b/src/coreComponents/constitutive/unitTests/CMakeLists.txt index 160c70a514e..069cb5ca646 100644 --- a/src/coreComponents/constitutive/unitTests/CMakeLists.txt +++ b/src/coreComponents/constitutive/unitTests/CMakeLists.txt @@ -7,7 +7,8 @@ set( gtest_geosx_tests testLinearElasticIsotropic.cpp testLinearElasticAnisotropic.cpp testRelPerm.cpp - testCapillaryPressure.cpp + testCapillaryPressure.cpp + testCO2BrinePVTModels.cpp ) set( dependencyList gtest ) diff --git a/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp b/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp new file mode 100644 index 00000000000..90732058212 --- /dev/null +++ b/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp @@ -0,0 +1,734 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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 Total, S.A + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +// Source includes +#include "codingUtilities/UnitTestUtilities.hpp" +#include "common/DataTypes.hpp" +#include "common/TimingMacros.hpp" +#include "constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp" +#include "managers/GeosxState.hpp" +#include "managers/initialization.hpp" + +// TPL includes +#include + +using namespace geosx; +using namespace geosx::testing; +using namespace geosx::constitutive; +using namespace geosx::dataRepository; +using namespace geosx::stringutilities; +using namespace geosx::PVTProps; + +/// Input tables written into temporary files during testing + +static const char * pvtliquid_str = "DensityFun BrineCO2Density 1e6 1.5e7 5e4 94 96 1 0.2\n" + "ViscosityFun BrineViscosity 0.1"; + +static const char * pvtgas_str = "DensityFun SpanWagnerCO2Density 1e6 1.5e7 5e4 94 96 1\n" + "ViscosityFun FenghourCO2Viscosity 1e6 1.5e7 5e4 94 96 1"; + +static const char * co2flash_str = "FlashModel CO2Solubility 1e6 1.5e7 5e4 94 96 1 0.15"; + +// TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION +void testValuesAgainstPreviousImplementation( PVTFunctionBaseUpdate const & pvtFunctionWrapper, + PVTFunction const & oldPvtFunction, + real64 const pressure, + real64 const temperature, + arraySlice1d< real64 > const & phaseComposition, + bool const useMass, + real64 const relTol ) +{ + real64 value = 0.0; + real64 dValue_dPressure = 0.0; + real64 dValue_dTemperature = 0.0; + stackArray1d< real64, 2 > dValue_dPhaseComposition( 2 ); + pvtFunctionWrapper.compute( pressure, + temperature, + phaseComposition, + value, + dValue_dPressure, + dValue_dTemperature, + dValue_dPhaseComposition, + useMass ); + + EvalVarArgs oldPres( pressure ); + EvalVarArgs oldTemp( temperature ); + EvalVarArgs oldValue( 0.0 ); + stackArray1d< EvalVarArgs, 2 > oldPhaseComposition( 2 ); + for( localIndex ic = 0; ic < 2; ic++ ) + { + oldPhaseComposition[ic].m_var = phaseComposition[ic]; + } + oldPvtFunction.evaluation( oldPres, + oldTemp, + oldPhaseComposition, + oldValue, + useMass ); + + checkRelativeError( value, oldValue.m_var, relTol ); +} + +// TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION +void testValuesAgainstPreviousImplementation( FlashModelBaseUpdate const & flashModelWrapper, + FlashModel const & oldFlashModel, + real64 const pressure, + real64 const temperature, + arraySlice1d< real64 > const & compFraction, + real64 const relTol ) +{ + stackArray1d< real64, 2 > phaseFraction( 2 ); + stackArray1d< real64, 2 > dPhaseFraction_dPres( 2 ); + stackArray1d< real64, 2 > dPhaseFraction_dTemp( 2 ); + stackArray2d< real64, 4 > dPhaseFraction_dCompFraction( 2, 2 ); + stackArray2d< real64, 4 > phaseCompFraction( 2, 2 ); + stackArray2d< real64, 4 > dPhaseCompFraction_dPres( 2, 2 ); + stackArray2d< real64, 4 > dPhaseCompFraction_dTemp( 2, 2 ); + stackArray3d< real64, 8 > dPhaseCompFraction_dCompFraction( 2, 2, 2 ); + flashModelWrapper.compute( pressure, + temperature, + compFraction, + phaseFraction, + dPhaseFraction_dPres, + dPhaseFraction_dTemp, + dPhaseFraction_dCompFraction, + phaseCompFraction, + dPhaseCompFraction_dPres, + dPhaseCompFraction_dTemp, + dPhaseCompFraction_dCompFraction ); + + EvalVarArgs oldPres( pressure ); + EvalVarArgs oldTemp( temperature ); + stackArray1d< EvalVarArgs, 2 > oldCompFraction( 2 ); + stackArray1d< EvalVarArgs, 2 > oldPhaseFraction( 2 ); + stackArray2d< EvalVarArgs, 4 > oldPhaseCompFraction( 2, 2 ); + for( localIndex ic = 0; ic < 2; ic++ ) + { + oldCompFraction[ic].m_var = compFraction[ic]; + } + oldFlashModel.partition( oldPres, + oldTemp, + oldCompFraction, + oldPhaseFraction, + oldPhaseCompFraction ); + + for( localIndex i = 0; i < 2; ++i ) + { + checkRelativeError( phaseFraction[i], oldPhaseFraction[i].m_var, relTol ); + for( localIndex j = 0; j < 2; ++j ) + { + checkRelativeError( phaseCompFraction[i][j], oldPhaseCompFraction[i][j].m_var, relTol ); + } + } +} + +void testNumericalDerivatives( PVTFunctionBaseUpdate const & pvtFunctionWrapper, + real64 const pressure, + real64 const temperature, + arraySlice1d< real64 > const & phaseComposition, + bool const useMass, + real64 const perturbParameter, + real64 const relTol ) +{ + // 1) First compute the unperturbed pressure + real64 value = 0.0; + real64 dValue_dPressure = 0.0; + real64 dValue_dTemperature = 0.0; + stackArray1d< real64, 2 > dValue_dPhaseComposition( 2 ); + pvtFunctionWrapper.compute( pressure, + temperature, + phaseComposition, + value, + dValue_dPressure, + dValue_dTemperature, + dValue_dPhaseComposition, + useMass ); + real64 perturbedValue = 0.0; + real64 dPerturbedValue_dPressure = 0.0; + real64 dPerturbedValue_dTemperature = 0.0; + stackArray1d< real64, 2 > dPerturbedValue_dPhaseComposition( 2 ); + + // 2) Check derivative with respect to pressure + real64 const dP = perturbParameter * (pressure + perturbParameter); + pvtFunctionWrapper.compute( pressure + dP, + temperature, + phaseComposition, + perturbedValue, + dPerturbedValue_dPressure, + dPerturbedValue_dTemperature, + dPerturbedValue_dPhaseComposition, + useMass ); + checkRelativeError( (perturbedValue-value)/dP, dValue_dPressure, relTol ); + + // 3) Check derivative with respect to temperature + real64 const dT = perturbParameter * (temperature + perturbParameter); + pvtFunctionWrapper.compute( pressure, + temperature + dT, + phaseComposition, + perturbedValue, + dPerturbedValue_dPressure, + dPerturbedValue_dTemperature, + dPerturbedValue_dPhaseComposition, + useMass ); + checkRelativeError( (perturbedValue-value)/dT, dValue_dTemperature, relTol ); + + // 4) Check derivatives with respect to phaseComposition + for( localIndex i = 0; i < 2; ++i ) + { + real64 const dC = perturbParameter * (phaseComposition[i] + perturbParameter); + stackArray1d< real64, 2 > perturbedPhaseComposition( 2 ); + for( localIndex j = 0; j < 2; ++j ) + { + perturbedPhaseComposition[j] = phaseComposition[j] + ( (i == j) ? dC : 0.0 ); + perturbedPhaseComposition[j] /= ( 1 + dC ); + } + pvtFunctionWrapper.compute( pressure, + temperature, + perturbedPhaseComposition, + perturbedValue, + dPerturbedValue_dPressure, + dPerturbedValue_dTemperature, + dPerturbedValue_dPhaseComposition, + useMass ); + checkRelativeError( (perturbedValue-value)/dC, dValue_dPhaseComposition[i], relTol ); + } +} + +void testNumericalDerivatives( FlashModelBaseUpdate const & flashModelWrapper, + real64 const pressure, + real64 const temperature, + arraySlice1d< real64 > const & compFraction, + real64 const perturbParameter, + real64 const relTol ) +{ + // 1) First compute the unperturbed pressure + stackArray1d< real64, 2 > phaseFraction( 2 ); + stackArray1d< real64, 2 > dPhaseFraction_dPres( 2 ); + stackArray1d< real64, 2 > dPhaseFraction_dTemp( 2 ); + stackArray2d< real64, 4 > dPhaseFraction_dCompFraction( 2, 2 ); + stackArray2d< real64, 4 > phaseCompFraction( 2, 2 ); + stackArray2d< real64, 4 > dPhaseCompFraction_dPres( 2, 2 ); + stackArray2d< real64, 4 > dPhaseCompFraction_dTemp( 2, 2 ); + stackArray3d< real64, 8 > dPhaseCompFraction_dCompFraction( 2, 2, 2 ); + flashModelWrapper.compute( pressure, + temperature, + compFraction, + phaseFraction, + dPhaseFraction_dPres, + dPhaseFraction_dTemp, + dPhaseFraction_dCompFraction, + phaseCompFraction, + dPhaseCompFraction_dPres, + dPhaseCompFraction_dTemp, + dPhaseCompFraction_dCompFraction ); + stackArray1d< real64, 2 > perturbedPhaseFraction( 2 ); + stackArray1d< real64, 2 > dPerturbedPhaseFraction_dPres( 2 ); + stackArray1d< real64, 2 > dPerturbedPhaseFraction_dTemp( 2 ); + stackArray2d< real64, 4 > dPerturbedPhaseFraction_dCompFraction( 2, 2 ); + stackArray2d< real64, 4 > perturbedPhaseCompFraction( 2, 2 ); + stackArray2d< real64, 4 > dPerturbedPhaseCompFraction_dPres( 2, 2 ); + stackArray2d< real64, 4 > dPerturbedPhaseCompFraction_dTemp( 2, 2 ); + stackArray3d< real64, 8 > dPerturbedPhaseCompFraction_dCompFraction( 2, 2, 2 ); + + // 2) Check derivative with respect to pressure + real64 const dP = perturbParameter * (pressure + perturbParameter); + flashModelWrapper.compute( pressure + dP, + temperature, + compFraction, + perturbedPhaseFraction, + dPerturbedPhaseFraction_dPres, + dPerturbedPhaseFraction_dTemp, + dPerturbedPhaseFraction_dCompFraction, + perturbedPhaseCompFraction, + dPerturbedPhaseCompFraction_dPres, + dPerturbedPhaseCompFraction_dTemp, + dPerturbedPhaseCompFraction_dCompFraction ); + for( localIndex i = 0; i < 2; ++i ) + { + checkRelativeError( (perturbedPhaseFraction[i]-phaseFraction[i])/dP, dPhaseFraction_dPres[i], relTol ); + for( localIndex j = 0; j < 2; ++j ) + { + checkRelativeError( (perturbedPhaseCompFraction[i][j]-phaseCompFraction[i][j])/dP, dPhaseCompFraction_dPres[i][j], relTol ); + } + } + + // 3) Check derivative with respect to temperature + real64 const dT = perturbParameter * (temperature + perturbParameter); + flashModelWrapper.compute( pressure, + temperature + dT, + compFraction, + perturbedPhaseFraction, + dPerturbedPhaseFraction_dPres, + dPerturbedPhaseFraction_dTemp, + dPerturbedPhaseFraction_dCompFraction, + perturbedPhaseCompFraction, + dPerturbedPhaseCompFraction_dPres, + dPerturbedPhaseCompFraction_dTemp, + dPerturbedPhaseCompFraction_dCompFraction ); + for( localIndex i = 0; i < 2; ++i ) + { + checkRelativeError( (perturbedPhaseFraction[i]-phaseFraction[i])/dT, dPhaseFraction_dTemp[i], relTol ); + for( localIndex j = 0; j < 2; ++j ) + { + checkRelativeError( (perturbedPhaseCompFraction[i][j]-phaseCompFraction[i][j])/dT, dPhaseCompFraction_dTemp[i][j], relTol ); + } + } + + // 4) Check derivatives with respect to phaseComposition + for( localIndex i = 0; i < 2; ++i ) + { + real64 const dC = perturbParameter * (compFraction[i] + perturbParameter); + stackArray1d< real64, 2 > perturbedCompFraction( 2 ); + for( localIndex j = 0; j < 2; ++j ) + { + perturbedCompFraction[j] = compFraction[j] + ( (i == j) ? dC : 0.0 ); + perturbedCompFraction[j] /= ( 1 + dC ); + } + flashModelWrapper.compute( pressure, + temperature, + perturbedCompFraction, + perturbedPhaseFraction, + dPerturbedPhaseFraction_dPres, + dPerturbedPhaseFraction_dTemp, + dPerturbedPhaseFraction_dCompFraction, + perturbedPhaseCompFraction, + dPerturbedPhaseCompFraction_dPres, + dPerturbedPhaseCompFraction_dTemp, + dPerturbedPhaseCompFraction_dCompFraction ); + for( localIndex j = 0; j < 2; ++j ) + { + checkRelativeError( (perturbedPhaseFraction[j]-phaseFraction[j])/dC, dPhaseFraction_dCompFraction[j][i], relTol ); + for( localIndex k = 0; k < 2; ++k ) + { + checkRelativeError( (perturbedPhaseCompFraction[j][k]-phaseCompFraction[j][k])/dC, dPhaseCompFraction_dCompFraction[j][k][i], relTol ); + } + } + } + +} + +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 ); +} + +template< typename MODEL > +std::unique_ptr< MODEL > makePVTFunction( string const & filename, + string const & key ) +{ + // define component names and molar weight + array1d< string > componentNames; + componentNames.resize( 2 ); + componentNames[0] = "co2"; componentNames[1] = "water"; + + array1d< real64 > componentMolarWeight; + componentMolarWeight.resize( 2 ); + componentMolarWeight[0] = 44e-3; componentMolarWeight[1] = 18e-3; + + // read parameters from file + std::ifstream is( filename ); + + constexpr std::streamsize buf_size = 256; + char buf[buf_size]; + + std::unique_ptr< MODEL > pvtFunction = nullptr; + + while( is.getline( buf, buf_size )) + { + string const str( buf ); + string_array const strs = Tokenize( str, " " ); + + if( strs[0] == key ) + { + pvtFunction = std::make_unique< MODEL >( strs, + componentNames, + componentMolarWeight ); + } + } + GEOSX_ERROR_IF( pvtFunction == nullptr, + "Could not find " << key << " in " << filename ); + + return pvtFunction; +} + +template< typename MODEL > +std::unique_ptr< MODEL > makeFlashModel( string const & filename, + string const & key ) +{ + // define phase names + array1d< string > phaseNames; + phaseNames.resize( 2 ); + phaseNames[0] = "gas"; phaseNames[1] = "liquid"; + + // define component names and molar weight + array1d< string > componentNames; + componentNames.resize( 2 ); + componentNames[0] = "co2"; componentNames[1] = "water"; + + array1d< real64 > componentMolarWeight; + componentMolarWeight.resize( 2 ); + componentMolarWeight[0] = 44e-3; componentMolarWeight[1] = 18e-3; + + // read parameters from file + std::ifstream is( filename ); + + constexpr std::streamsize buf_size = 256; + char buf[buf_size]; + + std::unique_ptr< MODEL > flashModel = nullptr; + + while( is.getline( buf, buf_size )) + { + string const str( buf ); + string_array const strs = Tokenize( str, " " ); + + if( strs[0] == key ) + { + flashModel = std::make_unique< MODEL >( strs, + phaseNames, + componentNames, + componentMolarWeight ); + } + } + GEOSX_ERROR_IF( flashModel == nullptr, + "Could not find " << key << " in " << filename ); + + return flashModel; +} + + +class BrineViscosityTest : public ::testing::Test +{ +protected: + + virtual void SetUp() override + { + writeTableToFile( filename, pvtliquid_str ); + + pvtFunction = makePVTFunction< BrineViscosity >( filename, key ); + oldPvtFunction = makePVTFunction< BrineViscosityFunction >( filename, key ); // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION + } + + virtual void TearDown() override + { + removeFile( filename ); + } + + string const key = "ViscosityFun"; + string const filename = "pvtliquid.txt"; + + std::unique_ptr< BrineViscosity > pvtFunction; + std::unique_ptr< BrineViscosityFunction > oldPvtFunction; // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION +}; + +TEST_F( BrineViscosityTest, brineViscosityValuesAndDeriv ) +{ + real64 const P[3] = { 5e6, 7.5e6, 1.2e7 }; + real64 const TC[3] = { 94.5, 95, 95.6 }; + array1d< real64 > comp( 2 ); + comp[0] = 0.3; comp[1] = 0.7; + + real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); + real64 const relTol = 5e-5; + + BrineViscosity::KernelWrapper pvtFunctionWrapper = pvtFunction->createKernelWrapper(); + + for( localIndex iPres = 0; iPres < 3; ++iPres ) + { + for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + { + testValuesAgainstPreviousImplementation( pvtFunctionWrapper, // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION + *oldPvtFunction, P[iPres], TC[iTemp], comp, true, relTol ); + testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, true, eps, relTol ); + } + } +} + +class FenghourCO2ViscosityTest : public ::testing::Test +{ +protected: + + virtual void SetUp() override + { + writeTableToFile( filename, pvtgas_str ); + + pvtFunction = makePVTFunction< FenghourCO2Viscosity >( filename, key ); + oldPvtFunction = makePVTFunction< FenghourCO2ViscosityFunction >( filename, key ); // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION + } + + virtual void TearDown() override + { + removeFile( filename ); + } + + string const key = "ViscosityFun"; + string const filename = "pvtgas.txt"; + + std::unique_ptr< FenghourCO2Viscosity > pvtFunction; + std::unique_ptr< FenghourCO2ViscosityFunction > oldPvtFunction; // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION +}; + +TEST_F( FenghourCO2ViscosityTest, fenghourCO2ViscosityValuesAndDeriv ) +{ + // when checking numerical derivatives, do not fall on the coordinate points of the tables!! + // (see the txt file defined at the top of the file for the definition of the coordinates) + real64 const P[3] = { 5.012e6, 7.546e6, 1.289e7 }; + real64 const TC[3] = { 94.5, 95.1, 95.6 }; + array1d< real64 > comp( 2 ); + comp[0] = 0.3; comp[1] = 0.7; + + real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); + real64 const relTol = 5e-5; + + FenghourCO2Viscosity::KernelWrapper pvtFunctionWrapper = pvtFunction->createKernelWrapper(); + + for( localIndex iPres = 0; iPres < 3; ++iPres ) + { + for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + { + testValuesAgainstPreviousImplementation( pvtFunctionWrapper, // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION + *oldPvtFunction, P[iPres], TC[iTemp], comp, true, relTol ); + testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, true, eps, relTol ); + } + } +} + +class BrineCO2DensityTest : public ::testing::Test +{ +protected: + + virtual void SetUp() override + { + writeTableToFile( filename, pvtliquid_str ); + + pvtFunction = makePVTFunction< BrineCO2Density >( filename, key ); + oldPvtFunction = makePVTFunction< BrineCO2DensityFunction >( filename, key ); // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION + } + + virtual void TearDown() override + { + removeFile( filename ); + } + + string const key = "DensityFun"; + string const filename = "pvtliquid.txt"; + + std::unique_ptr< BrineCO2Density > pvtFunction; + std::unique_ptr< BrineCO2DensityFunction > oldPvtFunction; // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION +}; + +TEST_F( BrineCO2DensityTest, brineCO2DensityMassValuesAndDeriv ) +{ + // when checking numerical derivatives, do not fall on the coordinate points of the tables!! + // (see the txt file defined at the top of the file for the definition of the coordinates) + real64 const P[3] = { 5.012e6, 7.546e6, 1.289e7 }; + real64 const TC[3] = { 94.5, 95.1, 95.6 }; + array1d< real64 > comp( 2 ); + comp[0] = 0.3; comp[1] = 0.7; + + real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); + real64 const relTol = 5e-5; + + BrineCO2Density::KernelWrapper pvtFunctionWrapper = pvtFunction->createKernelWrapper(); + + for( localIndex iPres = 0; iPres < 3; ++iPres ) + { + for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + { + testValuesAgainstPreviousImplementation( pvtFunctionWrapper, // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION + *oldPvtFunction, P[iPres], TC[iTemp], comp, true, relTol ); + testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, true, eps, relTol ); + } + } +} + +TEST_F( BrineCO2DensityTest, brineCO2DensityMolarValuesAndDeriv ) +{ + // when checking numerical derivatives, do not fall on the coordinate points of the tables!! + // (see the txt file defined at the top of the file for the definition of the coordinates) + real64 const P[3] = { 5.012e6, 7.546e6, 1.289e7 }; + real64 const TC[3] = { 94.5, 95.1, 95.6 }; + array1d< real64 > comp( 2 ); + comp[0] = 0.3; comp[1] = 0.7; + + real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); + real64 const relTol = 5e-5; + + BrineCO2Density::KernelWrapper pvtFunctionWrapper = pvtFunction->createKernelWrapper(); + + for( localIndex iPres = 0; iPres < 3; ++iPres ) + { + for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + { + testValuesAgainstPreviousImplementation( pvtFunctionWrapper, // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION + *oldPvtFunction, P[iPres], TC[iTemp], comp, false, relTol ); + testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, false, eps, relTol ); + } + } +} + + +class SpanWagnerCO2DensityTest : public ::testing::Test +{ +protected: + + virtual void SetUp() override + { + writeTableToFile( filename, pvtgas_str ); + + pvtFunction = makePVTFunction< SpanWagnerCO2Density >( filename, key ); + oldPvtFunction = makePVTFunction< SpanWagnerCO2DensityFunction >( filename, key ); // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION + } + + virtual void TearDown() override + { + removeFile( filename ); + } + + string const key = "DensityFun"; + string const filename = "pvtgas.txt"; + + std::unique_ptr< SpanWagnerCO2Density > pvtFunction; + std::unique_ptr< SpanWagnerCO2DensityFunction > oldPvtFunction; // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION +}; + +TEST_F( SpanWagnerCO2DensityTest, spanWagnerCO2DensityMassValuesAndDeriv ) +{ + // when checking numerical derivatives, do not fall on the coordinate points of the tables!! + // (see the txt file defined at the top of the file for the definition of the coordinates) + real64 const P[3] = { 5.012e6, 7.546e6, 1.289e7 }; + real64 const TC[3] = { 94.5, 95.1, 95.6 }; + array1d< real64 > comp( 2 ); + comp[0] = 0.3; comp[1] = 0.7; + + real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); + real64 const relTol = 5e-5; + + SpanWagnerCO2Density::KernelWrapper pvtFunctionWrapper = pvtFunction->createKernelWrapper(); + + for( localIndex iPres = 0; iPres < 3; ++iPres ) + { + for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + { + testValuesAgainstPreviousImplementation( pvtFunctionWrapper, // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION + *oldPvtFunction, P[iPres], TC[iTemp], comp, true, relTol ); + testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, true, eps, relTol ); + } + } +} + +TEST_F( SpanWagnerCO2DensityTest, spanWagnerCO2DensityMolarValuesAndDeriv ) +{ + // when checking numerical derivatives, do not fall on the coordinate points of the tables!! + // (see the txt file defined at the top of the file for the definition of the coordinates) + real64 const P[3] = { 5.012e6, 7.546e6, 1.289e7 }; + real64 const TC[3] = { 94.5, 95.1, 95.6 }; + array1d< real64 > comp( 2 ); + comp[0] = 0.3; comp[1] = 0.7; + + real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); + real64 const relTol = 5e-5; + + SpanWagnerCO2Density::KernelWrapper pvtFunctionWrapper = pvtFunction->createKernelWrapper(); + + for( localIndex iPres = 0; iPres < 3; ++iPres ) + { + for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + { + testValuesAgainstPreviousImplementation( pvtFunctionWrapper, // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION + *oldPvtFunction, P[iPres], TC[iTemp], comp, false, relTol ); + testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, false, eps, relTol ); + } + } +} + + +class CO2SolubilityTest : public ::testing::Test +{ +protected: + + virtual void SetUp() override + { + writeTableToFile( filename, co2flash_str ); + + flashModel = makeFlashModel< CO2Solubility >( filename, key ); + oldFlashModel = makeFlashModel< CO2SolubilityFunction >( filename, key ); // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION + } + + virtual void TearDown() override + { + removeFile( filename ); + } + + string const key = "FlashModel"; + string const filename = "co2flash.txt"; + + std::unique_ptr< CO2Solubility > flashModel; + std::unique_ptr< CO2SolubilityFunction > oldFlashModel; // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION +}; + +TEST_F( CO2SolubilityTest, co2SolubilityValuesAndDeriv ) +{ + // when checking numerical derivatives, do not fall on the coordinate points of the tables!! + // (see the txt file defined at the top of the file for the definition of the coordinates) + real64 const P[3] = { 5.012e6, 7.546e6, 1.289e7 }; + real64 const TC[3] = { 94.5, 95.1, 95.6 }; + array1d< real64 > comp( 2 ); + comp[0] = 0.3; comp[1] = 0.7; + + real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); + real64 const relTol = 5e-5; + + CO2Solubility::KernelWrapper flashModelWrapper = flashModel->createKernelWrapper(); + + for( localIndex iPres = 0; iPres < 3; ++iPres ) + { + for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + { + testValuesAgainstPreviousImplementation( flashModelWrapper, // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION + *oldFlashModel, P[iPres], TC[iTemp], comp, relTol ); + testNumericalDerivatives( flashModelWrapper, P[iPres], TC[iTemp], comp, eps, relTol ); + } + } +} + +int main( int argc, char * * argv ) +{ + ::testing::InitGoogleTest( &argc, argv ); + + geosx::GeosxState state( geosx::basicSetup( argc, argv ) ); + + int const result = RUN_ALL_TESTS(); + + geosx::basicCleanup(); + + return result; +} diff --git a/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp b/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp index ba23a95d58b..a3c8e6c64db 100644 --- a/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp +++ b/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp @@ -14,6 +14,7 @@ // Source includes #include "managers/initialization.hpp" +#include "managers/GeosxState.hpp" #include "common/DataTypes.hpp" #include "common/TimingMacros.hpp" #include "constitutive/fluid/multiFluidSelector.hpp" @@ -28,6 +29,7 @@ using namespace geosx; using namespace geosx::testing; using namespace geosx::constitutive; using namespace geosx::dataRepository; +using namespace geosx::PVTProps; /// Black-oil tables written into temporary files during testing @@ -109,6 +111,16 @@ static const char * pvdo_str = "#P[Pa]\tBo[m3/sm3]\tVisc(Pa.s)\n" static const char * pvdw_str = "#\tPref[bar]\tBw[m3/sm3]\tCp[1/bar]\t Visc[cP]\n" "\t30600000.1\t1.03\t\t0.00000000041\t0.0003"; +// CO2-brine model + +static const char * pvtliquid_str = "DensityFun BrineCO2Density 1e6 1.5e7 5e4 94 96 1 0.2\n" + "ViscosityFun BrineViscosity 0.1"; + +static const char * pvtgas_str = "DensityFun SpanWagnerCO2Density 1e6 1.5e7 5e4 94 96 1\n" + "ViscosityFun FenghourCO2Viscosity 1e6 1.5e7 5e4 94 96 1"; + +static const char * co2flash_str = "FlashModel CO2Solubility 1e6 1.5e7 5e4 94 96 1 0.15"; + void testNumericalDerivatives( MultiFluidBase & fluid, Group & parent, real64 const P, @@ -269,6 +281,112 @@ void testNumericalDerivatives( MultiFluidBase & fluid, } ); } +// TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION +void testValuesAgainstPreviousImplementation( NewMultiPhaseMultiComponentFluid::KernelWrapper const & wrapper, + MultiPhaseMultiComponentFluid::KernelWrapper const & oldWrapper, + real64 const P, + real64 const T, + arraySlice1d< real64 > const & composition, + real64 const relTol ) +{ + stackArray1d< real64, 2 > phaseFraction( 2 ); + stackArray1d< real64, 2 > dPhaseFraction_dPressure( 2 ); + stackArray1d< real64, 2 > dPhaseFraction_dTemperature( 2 ); + stackArray2d< real64, 4 > dPhaseFraction_dGlobalCompFraction( 2, 2 ); + stackArray1d< real64, 2 > phaseDensity( 2 ); + stackArray1d< real64, 2 > dPhaseDensity_dPressure( 2 ); + stackArray1d< real64, 2 > dPhaseDensity_dTemperature( 2 ); + stackArray2d< real64, 4 > dPhaseDensity_dGlobalCompFraction( 2, 2 ); + stackArray1d< real64, 2 > phaseMassDensity( 2 ); + stackArray1d< real64, 2 > dPhaseMassDensity_dPressure( 2 ); + stackArray1d< real64, 2 > dPhaseMassDensity_dTemperature( 2 ); + stackArray2d< real64, 4 > dPhaseMassDensity_dGlobalCompFraction( 2, 2 ); + stackArray1d< real64, 2 > phaseViscosity( 2 ); + stackArray1d< real64, 2 > dPhaseViscosity_dPressure( 2 ); + stackArray1d< real64, 2 > dPhaseViscosity_dTemperature( 2 ); + stackArray2d< real64, 4 > dPhaseViscosity_dGlobalCompFraction( 2, 2 ); + stackArray2d< real64, 4 > phaseCompFraction( 2, 2 ); + stackArray2d< real64, 4 > dPhaseCompFraction_dPressure( 2, 2 ); + stackArray2d< real64, 4 > dPhaseCompFraction_dTemperature( 2, 2 ); + stackArray3d< real64, 8 > dPhaseCompFraction_dGlobalCompFraction( 2, 2, 2 ); + real64 totalDensity = 0.0; + real64 dTotalDensity_dPressure = 0.0; + real64 dTotalDensity_dTemperature = 0.0; + stackArray1d< real64, 2 > dTotalDensity_dGlobalCompFraction( 2 ); + + stackArray1d< real64, 2 > oldPhaseFraction( 2 ); + stackArray1d< real64, 2 > oldPhaseDensity( 2 ); + stackArray1d< real64, 2 > oldPhaseMassDensity( 2 ); + stackArray1d< real64, 2 > oldPhaseViscosity( 2 ); + stackArray2d< real64, 4 > oldPhaseCompFraction( 2, 2 ); + real64 oldTotalDensity = 0.0; + + wrapper.compute( P, T, composition, + phaseFraction, + dPhaseFraction_dPressure, + dPhaseFraction_dTemperature, + dPhaseFraction_dGlobalCompFraction, + phaseDensity, + dPhaseDensity_dPressure, + dPhaseDensity_dTemperature, + dPhaseDensity_dGlobalCompFraction, + phaseMassDensity, + dPhaseMassDensity_dPressure, + dPhaseMassDensity_dTemperature, + dPhaseMassDensity_dGlobalCompFraction, + phaseViscosity, + dPhaseViscosity_dPressure, + dPhaseViscosity_dTemperature, + dPhaseViscosity_dGlobalCompFraction, + phaseCompFraction, + dPhaseCompFraction_dPressure, + dPhaseCompFraction_dTemperature, + dPhaseCompFraction_dGlobalCompFraction, + totalDensity, + dTotalDensity_dPressure, + dTotalDensity_dTemperature, + dTotalDensity_dGlobalCompFraction ); + + oldWrapper.compute( P, T, composition, + oldPhaseFraction, + dPhaseFraction_dPressure, + dPhaseFraction_dTemperature, + dPhaseFraction_dGlobalCompFraction, + oldPhaseDensity, + dPhaseDensity_dPressure, + dPhaseDensity_dTemperature, + dPhaseDensity_dGlobalCompFraction, + oldPhaseMassDensity, + dPhaseMassDensity_dPressure, + dPhaseMassDensity_dTemperature, + dPhaseMassDensity_dGlobalCompFraction, + oldPhaseViscosity, + dPhaseViscosity_dPressure, + dPhaseViscosity_dTemperature, + dPhaseViscosity_dGlobalCompFraction, + oldPhaseCompFraction, + dPhaseCompFraction_dPressure, + dPhaseCompFraction_dTemperature, + dPhaseCompFraction_dGlobalCompFraction, + oldTotalDensity, + dTotalDensity_dPressure, + dTotalDensity_dTemperature, + dTotalDensity_dGlobalCompFraction ); + + checkRelativeError( totalDensity, oldTotalDensity, relTol ); + for( localIndex ip = 0; ip < 2; ++ip ) + { + checkRelativeError( phaseFraction[ip], oldPhaseFraction[ip], relTol ); + checkRelativeError( phaseDensity[ip], oldPhaseDensity[ip], relTol ); + checkRelativeError( phaseMassDensity[ip], oldPhaseMassDensity[ip], relTol ); + checkRelativeError( phaseViscosity[ip], oldPhaseViscosity[ip], relTol ); + for( localIndex ic = 0; ic < 2; ++ic ) + { + checkRelativeError( phaseCompFraction[ip][ic], oldPhaseCompFraction[ip][ic], relTol ); + } + } +} + MultiFluidBase * makeCompositionalFluid( string const & name, Group & parent ) { auto fluid = parent.registerGroup< CompositionalMultiphaseFluid >( name ); @@ -561,11 +679,202 @@ TEST_F( DeadOilFluidTest, numericalDerivativesMass ) testNumericalDerivatives( *fluid, parent, P, T, comp, eps, relTol, absTol ); } +MultiFluidBase * makeMultiPhaseMultiComponentFluid( string const & name, Group * parent ) +{ + auto fluid = parent->registerGroup< NewMultiPhaseMultiComponentFluid >( name ); + + auto & compNames = fluid->getReference< string_array >( MultiFluidBase::viewKeyStruct::componentNamesString ); + compNames.resize( 2 ); + compNames[0] = "co2"; compNames[1] = "water"; + + auto & molarWgt = fluid->getReference< array1d< real64 > >( MultiFluidBase::viewKeyStruct::componentMolarWeightString ); + molarWgt.resize( 2 ); + molarWgt[0] = 44e-3; molarWgt[1] = 18e-3; + + auto & phaseNames = fluid->getReference< string_array >( MultiFluidBase::viewKeyStruct::phaseNamesString ); + phaseNames.resize( 2 ); + phaseNames[0] = "gas"; phaseNames[1] = "liquid"; + + auto & phasePVTParaFileNames = fluid->getReference< path_array >( MultiPhaseMultiComponentFluid::viewKeyStruct::phasePVTParaFilesString ); + phasePVTParaFileNames.resize( 2 ); + phasePVTParaFileNames[0] = "pvtgas.txt"; phasePVTParaFileNames[1] = "pvtliquid.txt"; + + auto & flashModelParaFileName = fluid->getReference< Path >( MultiPhaseMultiComponentFluid::viewKeyStruct::flashModelParaFileString ); + flashModelParaFileName = "co2flash.txt"; + + fluid->postProcessInputRecursive(); + return fluid; +} + +// TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION +MultiFluidBase * makeOldMultiPhaseMultiComponentFluid( string const & name, Group * parent ) +{ + auto fluid = parent->registerGroup< MultiPhaseMultiComponentFluid >( name ); + + auto & compNames = fluid->getReference< string_array >( MultiFluidBase::viewKeyStruct::componentNamesString ); + compNames.resize( 2 ); + compNames[0] = "co2"; compNames[1] = "water"; + + auto & molarWgt = fluid->getReference< array1d< real64 > >( MultiFluidBase::viewKeyStruct::componentMolarWeightString ); + molarWgt.resize( 2 ); + molarWgt[0] = 44e-3; molarWgt[1] = 18e-3; + + auto & phaseNames = fluid->getReference< string_array >( MultiFluidBase::viewKeyStruct::phaseNamesString ); + phaseNames.resize( 2 ); + phaseNames[0] = "gas"; phaseNames[1] = "liquid"; + + auto & phasePVTParaFileNames = fluid->getReference< path_array >( MultiPhaseMultiComponentFluid::viewKeyStruct::phasePVTParaFilesString ); + phasePVTParaFileNames.resize( 2 ); + phasePVTParaFileNames[0] = "pvtgas.txt"; phasePVTParaFileNames[1] = "pvtliquid.txt"; + + auto & flashModelParaFileName = fluid->getReference< Path >( MultiPhaseMultiComponentFluid::viewKeyStruct::flashModelParaFileString ); + flashModelParaFileName = "co2flash.txt"; + + fluid->postProcessInputRecursive(); + return fluid; +} + + +class MultiPhaseMultiComponentFluidTest : public CompositionalFluidTestBase +{ +protected: + + MultiPhaseMultiComponentFluidTest() + { + writeTableToFile( "pvtliquid.txt", pvtliquid_str ); + writeTableToFile( "pvtgas.txt", pvtgas_str ); + writeTableToFile( "co2flash.txt", co2flash_str ); + + parent.resize( 1 ); + fluid = makeMultiPhaseMultiComponentFluid( "fluid", &parent ); + oldFluid = makeOldMultiPhaseMultiComponentFluid( "oldFluid", &parent ); + + parent.initialize( &parent ); + parent.initializePostInitialConditions( &parent ); + } + + ~MultiPhaseMultiComponentFluidTest() + { + removeFile( "pvtliquid.txt" ); + removeFile( "pvtgas.txt" ); + removeFile( "co2flash.txt" ); + } + + MultiFluidBase * oldFluid; // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION +}; + +// TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION +TEST_F( MultiPhaseMultiComponentFluidTest, checkAgainstPreviousImplementationMolarTemporary ) +{ + fluid->setMassFlag( false ); + oldFluid->setMassFlag( false ); + + // TODO test over a range of values + real64 const P[3] = { 5e6, 7.5e6, 1.2e7 }; + real64 const T[3] = { 367.65, 368.15, 368.75 }; + array1d< real64 > comp( 2 ); + comp[0] = 0.3; comp[1] = 0.7; + + real64 const relTol = 1e-10; + + fluid->allocateConstitutiveData( fluid->getParent(), 1 ); + oldFluid->allocateConstitutiveData( oldFluid->getParent(), 1 ); + + NewMultiPhaseMultiComponentFluid::KernelWrapper wrapper = + dynamicCast< NewMultiPhaseMultiComponentFluid * >( fluid )->createKernelWrapper(); + MultiPhaseMultiComponentFluid::KernelWrapper oldWrapper = + dynamicCast< MultiPhaseMultiComponentFluid * >( oldFluid )->createKernelWrapper(); + + for( localIndex i = 0; i < 3; ++i ) + { + for( localIndex j = 0; j < 3; ++j ) + { + testValuesAgainstPreviousImplementation( wrapper, oldWrapper, P[i], T[j], comp, relTol ); + } + } +} + +// TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION +TEST_F( MultiPhaseMultiComponentFluidTest, checkAgainstPreviousImplementationMassTemporary ) +{ + fluid->setMassFlag( true ); + oldFluid->setMassFlag( true ); + + // TODO test over a range of values + real64 const P[3] = { 5e6, 7.5e6, 1.2e7 }; + real64 const T[3] = { 367.65, 368.15, 368.75 }; + array1d< real64 > comp( 2 ); + comp[0] = 0.3; comp[1] = 0.7; + + //real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); + real64 const relTol = 1e-10; + + fluid->allocateConstitutiveData( fluid->getParent(), 1 ); + oldFluid->allocateConstitutiveData( oldFluid->getParent(), 1 ); + + NewMultiPhaseMultiComponentFluid::KernelWrapper wrapper = + dynamicCast< NewMultiPhaseMultiComponentFluid * >( fluid )->createKernelWrapper(); + MultiPhaseMultiComponentFluid::KernelWrapper oldWrapper = + dynamicCast< MultiPhaseMultiComponentFluid * >( oldFluid )->createKernelWrapper(); + + for( localIndex i = 0; i < 3; ++i ) + { + for( localIndex j = 0; j < 3; ++j ) + { + testValuesAgainstPreviousImplementation( wrapper, oldWrapper, P[i], T[j], comp, relTol ); + } + } +} + +TEST_F( MultiPhaseMultiComponentFluidTest, numericalDerivativesMolar ) +{ + fluid->setMassFlag( false ); + + // TODO test over a range of values + real64 const P[3] = { 5e6, 7.5e6, 1.2e7 }; + real64 const T[3] = { 367.65, 368.15, 368.75 }; + array1d< real64 > comp( 2 ); + comp[0] = 0.3; comp[1] = 0.7; + + real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); + real64 const relTol = 1e-4; + + for( localIndex i = 0; i < 3; ++i ) + { + for( localIndex j = 0; j < 3; ++j ) + { + testNumericalDerivatives( *fluid, parent, P[i], T[j], comp, eps, relTol ); + } + } +} + +TEST_F( MultiPhaseMultiComponentFluidTest, numericalDerivativesMass ) +{ + fluid->setMassFlag( true ); + + // TODO test over a range of values + real64 const P[3] = { 5e6, 7.5e6, 1.2e7 }; + real64 const T[3] = { 367.65, 368.15, 368.75 }; + array1d< real64 > comp( 2 ); + comp[0] = 0.3; comp[1] = 0.7; + + real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); + real64 const relTol = 1e-4; + + for( localIndex i = 0; i < 3; ++i ) + { + for( localIndex j = 0; j < 3; ++j ) + { + testNumericalDerivatives( *fluid, parent, P[i], T[j], comp, eps, relTol ); + } + } +} + int main( int argc, char * * argv ) { ::testing::InitGoogleTest( &argc, argv ); - geosx::basicSetup( argc, argv ); + geosx::GeosxState state( geosx::basicSetup( argc, argv ) ); int const result = RUN_ALL_TESTS(); diff --git a/src/coreComponents/fileIO/schema/docs/Constitutive.rst b/src/coreComponents/fileIO/schema/docs/Constitutive.rst index 06ec905a795..a3d76963f38 100644 --- a/src/coreComponents/fileIO/schema/docs/Constitutive.rst +++ b/src/coreComponents/fileIO/schema/docs/Constitutive.rst @@ -18,6 +18,7 @@ LinearElasticAnisotropic node :ref:`XML_LinearElasticAnisot LinearElasticIsotropic node :ref:`XML_LinearElasticIsotropic` LinearElasticTransverseIsotropic node :ref:`XML_LinearElasticTransverseIsotropic` MultiPhaseMultiComponentFluid node :ref:`XML_MultiPhaseMultiComponentFluid` +NewMultiPhaseMultiComponentFluid node :ref:`XML_NewMultiPhaseMultiComponentFluid` NullModel node :ref:`XML_NullModel` ParticleFluid node :ref:`XML_ParticleFluid` PoreVolumeCompressibleSolid node :ref:`XML_PoreVolumeCompressibleSolid` diff --git a/src/coreComponents/fileIO/schema/docs/Constitutive_other.rst b/src/coreComponents/fileIO/schema/docs/Constitutive_other.rst index 9735b878313..a0893fad516 100644 --- a/src/coreComponents/fileIO/schema/docs/Constitutive_other.rst +++ b/src/coreComponents/fileIO/schema/docs/Constitutive_other.rst @@ -18,6 +18,7 @@ LinearElasticAnisotropic node :ref:`DATASTRUCTURE_LinearElasticAnis LinearElasticIsotropic node :ref:`DATASTRUCTURE_LinearElasticIsotropic` LinearElasticTransverseIsotropic node :ref:`DATASTRUCTURE_LinearElasticTransverseIsotropic` MultiPhaseMultiComponentFluid node :ref:`DATASTRUCTURE_MultiPhaseMultiComponentFluid` +NewMultiPhaseMultiComponentFluid node :ref:`DATASTRUCTURE_NewMultiPhaseMultiComponentFluid` NullModel node :ref:`DATASTRUCTURE_NullModel` ParticleFluid node :ref:`DATASTRUCTURE_ParticleFluid` PoreVolumeCompressibleSolid node :ref:`DATASTRUCTURE_PoreVolumeCompressibleSolid` diff --git a/src/coreComponents/fileIO/schema/docs/NewMultiPhaseMultiComponentFluid.rst b/src/coreComponents/fileIO/schema/docs/NewMultiPhaseMultiComponentFluid.rst new file mode 100644 index 00000000000..2010eb6efc8 --- /dev/null +++ b/src/coreComponents/fileIO/schema/docs/NewMultiPhaseMultiComponentFluid.rst @@ -0,0 +1,14 @@ + + +==================== ============ ======== ============================================================================== +Name Type Default Description +==================== ============ ======== ============================================================================== +componentMolarWeight real64_array {0} Component molar weights +componentNames string_array {} List of component names +flashModelParaFile path required Name of the file defining the parameters of the flash model +name string required A name is required for any non-unique nodes +phaseNames string_array {} List of fluid phases +phasePVTParaFiles path_array required Names of the files defining the parameters of the viscosity and density models +==================== ============ ======== ============================================================================== + + diff --git a/src/coreComponents/fileIO/schema/docs/NewMultiPhaseMultiComponentFluid_other.rst b/src/coreComponents/fileIO/schema/docs/NewMultiPhaseMultiComponentFluid_other.rst new file mode 100644 index 00000000000..5b3d3c27bb3 --- /dev/null +++ b/src/coreComponents/fileIO/schema/docs/NewMultiPhaseMultiComponentFluid_other.rst @@ -0,0 +1,33 @@ + + +====================================== ============================================================================================== ========================== +Name Type Description +====================================== ============================================================================================== ========================== +dPhaseCompFraction_dGlobalCompFraction LvArray_Array< double, 5, camp_int_seq< long, 0l, 1l, 2l, 3l, 4l >, long, LvArray_ChaiBuffer > (no description available) +dPhaseCompFraction_dPressure LvArray_Array< double, 4, camp_int_seq< long, 0l, 1l, 2l, 3l >, long, LvArray_ChaiBuffer > (no description available) +dPhaseCompFraction_dTemperature LvArray_Array< double, 4, camp_int_seq< long, 0l, 1l, 2l, 3l >, long, LvArray_ChaiBuffer > (no description available) +dPhaseDensity_dGlobalCompFraction LvArray_Array< double, 4, camp_int_seq< long, 0l, 1l, 2l, 3l >, long, LvArray_ChaiBuffer > (no description available) +dPhaseDensity_dPressure real64_array3d (no description available) +dPhaseDensity_dTemperature real64_array3d (no description available) +dPhaseFraction_dGlobalCompFraction LvArray_Array< double, 4, camp_int_seq< long, 0l, 1l, 2l, 3l >, long, LvArray_ChaiBuffer > (no description available) +dPhaseFraction_dPressure real64_array3d (no description available) +dPhaseFraction_dTemperature real64_array3d (no description available) +dPhaseMassDensity_dGlobalCompFraction LvArray_Array< double, 4, camp_int_seq< long, 0l, 1l, 2l, 3l >, long, LvArray_ChaiBuffer > (no description available) +dPhaseMassDensity_dPressure real64_array3d (no description available) +dPhaseMassDensity_dTemperature real64_array3d (no description available) +dPhaseViscosity_dGlobalCompFraction LvArray_Array< double, 4, camp_int_seq< long, 0l, 1l, 2l, 3l >, long, LvArray_ChaiBuffer > (no description available) +dPhaseViscosity_dPressure real64_array3d (no description available) +dPhaseViscosity_dTemperature real64_array3d (no description available) +dTotalDensity_dGlobalCompFraction real64_array3d (no description available) +dTotalDensity_dPressure real64_array2d (no description available) +dTotalDensity_dTemperature real64_array2d (no description available) +phaseCompFraction LvArray_Array< double, 4, camp_int_seq< long, 0l, 1l, 2l, 3l >, long, LvArray_ChaiBuffer > (no description available) +phaseDensity real64_array3d (no description available) +phaseFraction real64_array3d (no description available) +phaseMassDensity real64_array3d (no description available) +phaseViscosity real64_array3d (no description available) +totalDensity real64_array2d (no description available) +useMass integer (no description available) +====================================== ============================================================================================== ========================== + + diff --git a/src/coreComponents/fileIO/schema/schema.xsd b/src/coreComponents/fileIO/schema/schema.xsd index 53e8c1292ae..aa80cf529fa 100644 --- a/src/coreComponents/fileIO/schema/schema.xsd +++ b/src/coreComponents/fileIO/schema/schema.xsd @@ -1556,6 +1556,7 @@ Equal to 1 for surface conditions, and to 0 for reservoir conditions--> + @@ -1827,6 +1828,20 @@ Equal to 1 for surface conditions, and to 0 for reservoir conditions--> + + + + + + + + + + + + + + diff --git a/src/coreComponents/fileIO/schema/schema.xsd.other b/src/coreComponents/fileIO/schema/schema.xsd.other index 703b0143fd9..bb8ad5e110c 100644 --- a/src/coreComponents/fileIO/schema/schema.xsd.other +++ b/src/coreComponents/fileIO/schema/schema.xsd.other @@ -679,6 +679,7 @@ + @@ -978,6 +979,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/coreComponents/managers/Functions/TableFunction.cpp b/src/coreComponents/managers/Functions/TableFunction.cpp index 0f623ca0f39..afc179583f7 100644 --- a/src/coreComponents/managers/Functions/TableFunction.cpp +++ b/src/coreComponents/managers/Functions/TableFunction.cpp @@ -114,6 +114,32 @@ void TableFunction::parseFile( array1d< T > & target, string const & filename, c inputStream.close(); } +void TableFunction::setInterpolationMethod( InterpolationType const method ) +{ + m_interpolationMethod = method; + reInitializeFunction(); +} + +void TableFunction::setTableCoordinates( array1d< real64_array > coordinates ) +{ + m_coordinates.resize( 0 ); + for( localIndex i = 0; i < coordinates.size(); ++i ) + { + for( localIndex j = 1; j < coordinates[i].size(); ++j ) + { + GEOSX_ERROR_IF( coordinates[i][j] - coordinates[i][j-1] <= 0, + "In the table, the coordinates must be strictly increasing, but axis " << i << "is not" ); + } + m_coordinates.appendArray( coordinates[i].begin(), coordinates[i].end() ); + } + reInitializeFunction(); +} + +void TableFunction::setTableValues( real64_array values ) +{ + m_values = std::move( values ); + reInitializeFunction(); +} void TableFunction::initializeFunction() { @@ -127,7 +153,7 @@ void TableFunction::initializeFunction() { // 1D Table m_dimensions = 1; - m_coordinates.emplace_back( m_tableCoordinates1D ); + m_coordinates.appendArray( m_tableCoordinates1D.begin(), m_tableCoordinates1D.end() ); m_size.emplace_back( m_tableCoordinates1D.size()); // Check to make sure that the table dimensions match @@ -137,12 +163,14 @@ void TableFunction::initializeFunction() { // ND Table m_dimensions = LvArray::integerConversion< localIndex >( m_coordinateFiles.size()); - m_coordinates.resize( m_dimensions ); parseFile( m_values, m_voxelFile, ',' ); + array1d< real64 > tmp; for( localIndex ii=0; ii 0 && m_values.size() > 0 ) // coordinates and values have been set + { + GEOSX_ERROR_IF( increment != m_values.size(), "Table dimensions do not match!" ); + } // Build a quick map to help with linear interpolation m_numCorners = static_cast< localIndex >(pow( 2, m_dimensions )); @@ -177,129 +207,90 @@ void TableFunction::reInitializeFunction() m_corners[jj][ii] = int(ii / pow( 2, jj )) % 2; } } + + // Create the kernel wrapper + m_kernelWrapper.create( m_interpolationMethod, + m_coordinates.toViewConst(), + m_values.toViewConst(), + m_dimensions, + m_size.toViewConst(), + m_indexIncrement.toViewConst(), + m_corners, + m_numCorners ); + } +TableFunction::KernelWrapper TableFunction::createKernelWrapper() const +{ + return TableFunction::KernelWrapper( m_interpolationMethod, + m_coordinates.toViewConst(), + m_values.toViewConst(), + m_dimensions, + m_size.toViewConst(), + m_indexIncrement.toViewConst(), + m_corners, + m_numCorners ); +} real64 TableFunction::evaluate( real64 const * const input ) const { - real64 result = 0.0; - - // Linear interpolation - if( m_interpolationMethod == InterpolationType::Linear ) - { - localIndex bounds[m_maxDimensions][2]; - real64 weights[m_maxDimensions][2]; - - // Determine position, weights - for( localIndex ii=0; ii= m_coordinates[ii][m_size[ii] - 1] ) - { - // Coordinate is to the right of this axis - bounds[ii][0] = m_size[ii] - 1; - bounds[ii][1] = bounds[ii][0]; - weights[ii][0] = 1; - weights[ii][1] = 0; - } - else - { - // Find the coordinate index - ///TODO make this fast - // Note: lower_bound uses a binary search... If we assume coordinates are - // evenly spaced, we can speed things up considerably - auto lower = std::lower_bound( m_coordinates[ii].begin(), m_coordinates[ii].end(), input[ii] ); - bounds[ii][1] = LvArray::integerConversion< localIndex >( std::distance( m_coordinates[ii].begin(), lower )); - bounds[ii][0] = bounds[ii][1] - 1; - - real64 dx = m_coordinates[ii][bounds[ii][1]] - m_coordinates[ii][bounds[ii][0]]; - weights[ii][0] = 1.0 - (input[ii] - m_coordinates[ii][bounds[ii][0]]) / dx; - weights[ii][1] = 1.0 - weights[ii][0]; - } - } + real64 scalarValue = 0; + stackArray1d< real64, maxDimensions > derivativesArray( m_dimensions ); - // Calculate the result - for( localIndex ii=0; ii= m_coordinates[ii][m_size[ii] - 1] ) - { - // Coordinate is to the right of the table axis - subIndex = m_size[ii] - 1; - } - else - { - // Coordinate is within the table axis - // Note: std::distance will return the index of the upper table vertex - auto lower = std::lower_bound( m_coordinates[ii].begin(), m_coordinates[ii].end(), input[ii] ); - subIndex = LvArray::integerConversion< localIndex >( std::distance( m_coordinates[ii].begin(), lower )); - - // Interpolation types: - // - Nearest returns the value of the closest table vertex - // - Upper returns the value of the next table vertex - // - Lower returns the value of the previous table vertex - if( m_interpolationMethod == InterpolationType::Nearest ) - { - if((input[ii] - m_coordinates[ii][subIndex - 1]) <= (m_coordinates[ii][subIndex] - input[ii])) - { - --subIndex; - } - } - else if( m_interpolationMethod == InterpolationType::Lower ) - { - if( subIndex > 0 ) - { - --subIndex; - } - } - } + // interpolate in table, return scalar value (derivatives are discarded) + m_kernelWrapper.compute( input, scalarValue, derivativesArray ); + return scalarValue; +} - // Increment the global table index - tableIndex += subIndex * m_indexIncrement[ii]; - } +TableFunction::KernelWrapper::KernelWrapper( TableFunction::InterpolationType interpolationMethod, + ArrayOfArraysView< real64 const > const & coordinates, + arrayView1d< real64 const > const & values, + localIndex dimensions, + arrayView1d< localIndex const > const & size, + arrayView1d< localIndex const > const & indexIncrement, + localIndex const (&corners)[TableFunction::maxDimensions][16], + localIndex const numCorners ) + : + m_interpolationMethod( interpolationMethod ), + m_coordinates( coordinates ), + m_values( values ), + m_dimensions( dimensions ), + m_size( size ), + m_indexIncrement( indexIncrement ), + m_numCorners( numCorners ) +{ + LvArray::tensorOps::copy< TableFunction::maxDimensions, 16 >( m_corners, corners ); +} - // Retrieve the nearest value - result = m_values[tableIndex]; - } +TableFunction::KernelWrapper::KernelWrapper() + : + m_interpolationMethod(), + m_coordinates(), + m_values(), + m_dimensions( 0 ), + m_size(), + m_indexIncrement(), + m_numCorners( 0 ) +{} - return result; +void TableFunction::KernelWrapper::create( TableFunction::InterpolationType interpolationMethod, + ArrayOfArraysView< real64 const > const & coordinates, + arrayView1d< real64 const > const & values, + localIndex dimensions, + arrayView1d< localIndex const > const & size, + arrayView1d< localIndex const > const & indexIncrement, + localIndex const (&corners)[TableFunction::maxDimensions][16], + localIndex const numCorners ) +{ + m_interpolationMethod = interpolationMethod; + m_coordinates = coordinates; + m_values = values; + m_dimensions = dimensions; + m_size = size; + m_indexIncrement = indexIncrement; + m_numCorners = numCorners; + + LvArray::tensorOps::copy< TableFunction::maxDimensions, 16 >( m_corners, corners ); } REGISTER_CATALOG_ENTRY( FunctionBase, TableFunction, string const &, Group * const ) diff --git a/src/coreComponents/managers/Functions/TableFunction.hpp b/src/coreComponents/managers/Functions/TableFunction.hpp index 62652c2d788..1ea89ad91b2 100644 --- a/src/coreComponents/managers/Functions/TableFunction.hpp +++ b/src/coreComponents/managers/Functions/TableFunction.hpp @@ -21,6 +21,7 @@ #include "common/EnumStrings.hpp" #include "managers/Functions/FunctionBase.hpp" +#include "LvArray/src/tensorOps.hpp" namespace geosx { @@ -33,6 +34,125 @@ namespace geosx class TableFunction : public FunctionBase { public: + + /// Enumerator of available interpolation types + enum class InterpolationType : integer + { + Linear, + Nearest, + Upper, + Lower + }; + + /// maximum dimensions for the coordinates in the table + static constexpr localIndex maxDimensions = 4; + + /** + * @class KernelWrapper + * + * A nested class encapsulating the kernel function doing the interpolation in the table + */ + class KernelWrapper + { +public: + + /** + * @brief The constructor of the kernel wrapper + * @param[in] interpolationMethod table interpolation method + * @param[in] coordinates array of table axes + * @param[in] values table values (in fortran order) + * @param[in] dimensions number of active table dimensions + * @param[in] size size of the table + * @param[in] indexIncrement array used to locate values within ND tables + * @param[in] corners corners of the box that surround the value in N dimensions + * @param[in] numCorners number of active table corners + */ + KernelWrapper( TableFunction::InterpolationType interpolationMethod, + ArrayOfArraysView< real64 const > const & coordinates, + arrayView1d< real64 const > const & values, + localIndex dimensions, + arrayView1d< localIndex const > const & size, + arrayView1d< localIndex const > const & indexIncrement, + localIndex const (&corners)[TableFunction::maxDimensions][16], + localIndex const numCorners ); + + /// Default constructor for the kernel wrapper + KernelWrapper(); + + /// Default copy constructor + KernelWrapper( KernelWrapper const & ) = default; + + /// Default move constructor + KernelWrapper( KernelWrapper && ) = default; + + /// Copy assignment operator + KernelWrapper & operator=( KernelWrapper const & ) = delete; + + /// Deleted move assignment operator + KernelWrapper & operator=( KernelWrapper && ) = delete; + + /** + * @brief The function that populates the wrapper + * @param[in] interpolationMethod table interpolation method + * @param[in] coordinates array of table axes + * @param[in] values table values (in fortran order) + * @param[in] dimensions number of active table dimensions + * @param[in] size size of the table + * @param[in] indexIncrement array used to locate values within ND tables + * @param[in] corners corners of the box that surround the value in N dimensions + * @param[in] numCorners number of active table corners + */ + void create( TableFunction::InterpolationType interpolationMethod, + ArrayOfArraysView< real64 const > const & coordinates, + arrayView1d< real64 const > const & values, + localIndex dimensions, + arrayView1d< localIndex const > const & size, + arrayView1d< localIndex const > const & indexIncrement, + localIndex const (&corners)[TableFunction::maxDimensions][16], + localIndex const numCorners ); + + /** + * @brief Main compute function to interpolate in the table and return the derivatives + * @param[in] input vector of input value + * @param[out] value interpolated value + * @param[out] derivatives vector of derivatives of interpolated value wrt the variables present in input + */ + template< typename IN_ARRAY, typename OUT_ARRAY > + GEOSX_HOST_DEVICE + void + compute( IN_ARRAY const & input, real64 & value, OUT_ARRAY && derivatives ) const; + +private: + + /// Table interpolation method + TableFunction::InterpolationType m_interpolationMethod; + + /// An array of table axes + ArrayOfArraysView< real64 const > m_coordinates; + + /// Table values (in fortran order) + arrayView1d< real64 const > m_values; + + /// Number of active table dimensions + localIndex m_dimensions; + + /// Size of the table + arrayView1d< localIndex const > m_size; + + /// Array used to locate values within ND tables + arrayView1d< localIndex const > m_indexIncrement; + + /** + * @brief The corners of the box that surround the value in N dimensions + * m_corners should be of size m_maxDimensions x (2^m_maxDimensions) + */ + localIndex m_corners[TableFunction::maxDimensions][16]; + + /// The number of active table corners + localIndex m_numCorners; + + }; + /** * @brief The constructor * @param[in] name the name of this object manager @@ -99,12 +219,12 @@ class TableFunction : public FunctionBase * @brief Get the table axes definitions * @return a reference to an array of arrays that define each table axis */ - array1d< real64_array > const & getCoordinates() const { return m_coordinates; } + ArrayOfArraysView< real64 const > getCoordinates() const { return m_coordinates.toViewConst(); } /** * @copydoc getCoordinates() const */ - array1d< real64_array > & getCoordinates() { return m_coordinates; } + ArrayOfArraysView< real64 > getCoordinates() { return m_coordinates.toView(); } /** * @brief Get the table values @@ -117,32 +237,35 @@ class TableFunction : public FunctionBase */ array1d< real64 > & getValues() { return m_values; } - /// Enumerator of available interpolation types - enum class InterpolationType : integer - { - Linear, - Nearest, - Upper, - Lower - }; + /** + * @brief Get the interpolation method + * @return The interpolation method + */ + InterpolationType getInterpolationMethod() const { return m_interpolationMethod; } /** * @brief Set the interpolation method * @param method The interpolation method */ - void setInterpolationMethod( InterpolationType const method ) { m_interpolationMethod = method; } + void setInterpolationMethod( InterpolationType const method ); /** * @brief Set the table coordinates * @param coordinates An array of arrays containing table coordinate definitions */ - void setTableCoordinates( array1d< real64_array > coordinates ) { m_coordinates = coordinates; } + void setTableCoordinates( array1d< real64_array > coordinates ); /** * @brief Set the table values * @param values An array of table values in fortran order */ - void setTableValues( real64_array values ) { m_values = values; } + void setTableValues( real64_array values ); + + /** + * @brief Create an instance of the kernel wrapper + * @return the kernel wrapper + */ + KernelWrapper createKernelWrapper() const; private: /// Coordinates for 1D table @@ -158,14 +281,11 @@ class TableFunction : public FunctionBase InterpolationType m_interpolationMethod; /// An array of table axes - array1d< real64_array > m_coordinates; + ArrayOfArrays< real64 > m_coordinates; /// Table values (in fortran order) real64_array m_values; - /// Maximum number of table dimensions - static localIndex constexpr m_maxDimensions = 4; - /// Number of active table dimensions localIndex m_dimensions; @@ -177,16 +297,170 @@ class TableFunction : public FunctionBase /** * @brief The corners of the box that surround the value in N dimensions - * m_corners should be of size m_maxDimensions x (2^m_maxDimensions) + * m_corners should be of size maxDimensions x (2^maxDimensions) */ - localIndex m_corners[m_maxDimensions][16]; + localIndex m_corners[maxDimensions][16]; /// The number of active table corners localIndex m_numCorners; + + /// Kernel wrapper to interpolate in table and return derivatives + KernelWrapper m_kernelWrapper; + }; -ENUM_STRINGS( TableFunction::InterpolationType, "linear", "nearest", "upper", "lower" ) +template< typename IN_ARRAY, typename OUT_ARRAY > +GEOSX_HOST_DEVICE +void +TableFunction::KernelWrapper::compute( IN_ARRAY const & input, real64 & value, OUT_ARRAY && derivatives ) const +{ + value = 0.0; + for( localIndex i = 0; i < m_dimensions; ++i ) + { + derivatives[i] = 0.0; + } + // Linear interpolation + if( m_interpolationMethod == TableFunction::InterpolationType::Linear ) + { + localIndex bounds[TableFunction::maxDimensions][2]{}; + real64 weights[TableFunction::maxDimensions][2]{}; + real64 dWeights_dInput[TableFunction::maxDimensions][2]{}; + real64 dCornerValue_dInput[TableFunction::maxDimensions]{}; + + // Determine position, weights + for( localIndex ii=0; ii= m_coordinates[ii][m_size[ii] - 1] ) + { + // Coordinate is to the right of this axis + bounds[ii][0] = m_size[ii] - 1; + bounds[ii][1] = bounds[ii][0]; + weights[ii][0] = 1; + weights[ii][1] = 0; + dWeights_dInput[ii][0] = 0; + dWeights_dInput[ii][1] = 0; + } + else + { + // Find the coordinate index + ///TODO make this fast + // Note: find uses a binary search... If we assume coordinates are + // evenly spaced, we can speed things up considerably + auto lower = LvArray::sortedArrayManipulation::find( m_coordinates[ii].begin(), m_coordinates.sizeOfArray( ii ), input[ii] ); + bounds[ii][1] = LvArray::integerConversion< localIndex >( lower ); + bounds[ii][0] = bounds[ii][1] - 1; + + real64 dx = m_coordinates[ii][bounds[ii][1]] - m_coordinates[ii][bounds[ii][0]]; + weights[ii][0] = 1.0 - (input[ii] - m_coordinates[ii][bounds[ii][0]]) / dx; + weights[ii][1] = 1.0 - weights[ii][0]; + dWeights_dInput[ii][0] = -1.0 / dx; + dWeights_dInput[ii][1] = -dWeights_dInput[ii][0]; + } + } + + // Calculate the result + for( localIndex ii=0; ii= m_coordinates[ii][m_size[ii] - 1] ) + { + // Coordinate is to the right of the table axis + subIndex = m_size[ii] - 1; + } + else + { + // Coordinate is within the table axis + // Note: std::distance will return the index of the upper table vertex + auto lower = LvArray::sortedArrayManipulation::find( m_coordinates[ii].begin(), m_coordinates.sizeOfArray( ii ), input[ii] ); + subIndex = LvArray::integerConversion< localIndex >( lower ); + + // Interpolation types: + // - Nearest returns the value of the closest table vertex + // - Upper returns the value of the next table vertex + // - Lower returns the value of the previous table vertex + if( m_interpolationMethod == TableFunction::InterpolationType::Nearest ) + { + if((input[ii] - m_coordinates[ii][subIndex - 1]) <= (m_coordinates[ii][subIndex] - input[ii])) + { + --subIndex; + } + } + else if( m_interpolationMethod == TableFunction::InterpolationType::Lower ) + { + if( subIndex > 0 ) + { + --subIndex; + } + } + } + + // Increment the global table index + tableIndex += subIndex * m_indexIncrement[ii]; + } + + // Retrieve the nearest value + value = m_values[tableIndex]; + } +} + +ENUM_STRINGS( TableFunction::InterpolationType, "linear", "nearest", "upper", "lower" ) } /* namespace geosx */ diff --git a/src/coreComponents/managers/unitTests/testFunctions.cpp b/src/coreComponents/managers/unitTests/testFunctions.cpp index 6ccca424c5a..ed18efb56a9 100644 --- a/src/coreComponents/managers/unitTests/testFunctions.cpp +++ b/src/coreComponents/managers/unitTests/testFunctions.cpp @@ -12,6 +12,7 @@ * ------------------------------------------------------------------------------------------------------------ */ +#include "codingUtilities/UnitTestUtilities.hpp" #include "gtest/gtest.h" #include "managers/initialization.hpp" #include "managers/Functions/FunctionManager.hpp" @@ -28,7 +29,6 @@ using namespace geosx; - void evaluate1DFunction( FunctionBase * function, arrayView1d< real64 const > const & inputs, arrayView1d< real64 const > const & outputs ) @@ -43,15 +43,32 @@ void evaluate1DFunction( FunctionBase * function, } } +void checkDirectionalDerivative( real64 const (&input)[4], + real64 (& perturbedInput)[4], + real64 const & val, + real64 & perturbedVal, + real64 const (&derivatives)[4], + real64 (& perturbedDerivatives)[4], + real64 const & perturb, + real64 const & relTol, + localIndex const direction, + TableFunction::KernelWrapper kernelWrapper ) +{ + LvArray::tensorOps::copy< 4 >( perturbedInput, input ); + real64 const dInput = perturb * ( input[direction] + perturb ); + perturbedInput[direction] += dInput; + kernelWrapper.compute( perturbedInput, perturbedVal, perturbedDerivatives ); + geosx::testing::checkRelativeError( derivatives[direction], (perturbedVal-val)/dInput, relTol, geosx::testing::DEFAULT_ABS_TOL ); +} TEST( FunctionTests, 1DTable ) { FunctionManager * functionManager = &getGlobalState().getFunctionManager(); // 1D table, various interpolation methods - localIndex Naxis = 4; - localIndex Ntest = 6; + localIndex const Naxis = 4; + localIndex const Ntest = 6; // Setup table array1d< real64_array > coordinates; @@ -91,6 +108,7 @@ TEST( FunctionTests, 1DTable ) testExpected[4] = 3.0; testExpected[5] = 7.0; table_a->setInterpolationMethod( TableFunction::InterpolationType::Linear ); + table_a->reInitializeFunction(); evaluate1DFunction( table_a, testCoordinates, testExpected ); // Upper @@ -101,6 +119,7 @@ TEST( FunctionTests, 1DTable ) testExpected[4] = 7.0; testExpected[5] = 7.0; table_a->setInterpolationMethod( TableFunction::InterpolationType::Upper ); + table_a->reInitializeFunction(); evaluate1DFunction( table_a, testCoordinates, testExpected ); // Lower @@ -111,6 +130,7 @@ TEST( FunctionTests, 1DTable ) testExpected[4] = -5.0; testExpected[5] = 7.0; table_a->setInterpolationMethod( TableFunction::InterpolationType::Lower ); + table_a->reInitializeFunction(); evaluate1DFunction( table_a, testCoordinates, testExpected ); // Nearest @@ -121,6 +141,7 @@ TEST( FunctionTests, 1DTable ) testExpected[4] = 7.0; testExpected[5] = 7.0; table_a->setInterpolationMethod( TableFunction::InterpolationType::Nearest ); + table_a->reInitializeFunction(); evaluate1DFunction( table_a, testCoordinates, testExpected ); } @@ -133,11 +154,11 @@ TEST( FunctionTests, 2DTable ) // 2D table with linear interpolation // f(x, y) = 2*x - 3*y + 5 - localIndex Ndim = 2; - localIndex Nx = 3; - localIndex Ny = 4; - localIndex Ntest = 20; - string inputName = "coordinates"; + localIndex const Ndim = 2; + localIndex const Nx = 3; + localIndex const Ny = 4; + localIndex const Ntest = 20; + string const inputName = "coordinates"; // Setup table array1d< real64_array > coordinates; @@ -158,8 +179,8 @@ TEST( FunctionTests, 2DTable ) { for( localIndex ii=0; ii coordinates; @@ -275,10 +296,10 @@ TEST( FunctionTests, 4DTable_multipleInputs ) { for( localIndex ii=0; ii coordinates; + coordinates.resize( Ndim ); + coordinates[0].resize( Nx ); + coordinates[0][0] = -1.0; + coordinates[0][1] = 0.0; + coordinates[0][2] = 1.0; + coordinates[1].resize( Ny ); + coordinates[1][0] = -1.0; + coordinates[1][1] = 0.0; + coordinates[1][2] = 0.5; + coordinates[1][3] = 1.0; + coordinates[2].resize( Nz ); + coordinates[2][0] = -1.0; + coordinates[2][1] = -0.4; + coordinates[2][2] = 0.3; + coordinates[2][3] = 0.5; + coordinates[2][4] = 1.0; + coordinates[3].resize( Nt ); + coordinates[3][0] = -1.0; + coordinates[3][1] = 0.34; + coordinates[3][2] = 0.5; + coordinates[3][3] = 1.0; + + real64_array values( Nx * Ny * Nz * Nt ); + for( localIndex mm=0, tablePosition=0; mmcreateChild( "TableFunction", "table_d" )->groupCast< TableFunction * >(); + table_d->setTableCoordinates( coordinates ); + table_d->setTableValues( values ); + table_d->setInterpolationMethod( TableFunction::InterpolationType::Linear ); + table_d->setInputVarNames( inputVarNames ); + table_d->reInitializeFunction(); + + real64 const relTol = 1e-4; + real64 const eps = std::numeric_limits< real64 >::epsilon(); + real64 const perturb = std::sqrt( eps ); + + real64 const start = coordinates[0][0]-0.1; // start outside the table, to check derivatives there too + real64 const end = coordinates[0][Nx-1]+0.1; // end outside the table + localIndex const nSamples = 7; // try not to fall on table coordinate, otherwise the finite-difference approximation won't work + real64 const delta = (end-start)/nSamples; + + real64 val = 0.0; + real64 perturbedVal = 0.0; + real64 input[4] = { start, start, start, start }; + real64 perturbedInput[4]{}; + real64 derivatives[4]{}; + real64 perturbedDerivatives[4]{}; + + TableFunction::KernelWrapper kernelWrapper = table_d->createKernelWrapper(); + for( localIndex mm=0; mmcreateChild( "SymbolicFunction", "table_d" )->groupCast< SymbolicFunction * >(); - table_d->setSymbolicExpression( expression ); - table_d->setInputVarNames( inputVarNames ); - table_d->setSymbolicVariableNames( inputVarNames ); - table_d->initializeFunction(); + SymbolicFunction * table_e = functionManager->createChild( "SymbolicFunction", "table_e" )->groupCast< SymbolicFunction * >(); + table_e->setSymbolicExpression( expression ); + table_e->setInputVarNames( inputVarNames ); + table_e->setSymbolicVariableNames( inputVarNames ); + table_e->initializeFunction(); // Setup a group for testing the batch mode function evaluation conduit::Node node; dataRepository::Group testGroup( "testGroup", node ); + real64_array inputA; real64_array inputB; real64_array inputC; @@ -414,10 +551,10 @@ TEST( FunctionTests, 4DTable_symbolic ) // Build the inputs for( localIndex ii=0; iievaluate( &(testGroup), 0.0, set.toView(), output ); + table_e->evaluate( &(testGroup), 0.0, set.toView(), output ); // Compare results for( localIndex jj=0; jj Date: Fri, 26 Feb 2021 13:28:56 -0800 Subject: [PATCH 02/10] implemented Sergey's suggestion --- .../constitutive/CMakeLists.txt | 16 - .../constitutive/fluid/BlackOilFluid.hpp | 2 + .../fluid/CompositionalMultiphaseFluid.hpp | 2 + .../constitutive/fluid/MultiFluidBase.hpp | 4 +- .../fluid/MultiFluidPVTPackageWrapper.cpp | 11 +- .../fluid/MultiFluidPVTPackageWrapper.hpp | 5 + .../fluid/MultiPhaseMultiComponentFluid.cpp | 394 ++------ .../fluid/MultiPhaseMultiComponentFluid.hpp | 662 ++++++++++++- .../NewMultiPhaseMultiComponentFluid.cpp | 187 ---- .../NewMultiPhaseMultiComponentFluid.hpp | 885 ------------------ .../PVTFunctions/BrineCO2DensityFunction.cpp | 180 ++-- .../PVTFunctions/BrineCO2DensityFunction.hpp | 203 +++- .../PVTFunctions/BrineViscosityFunction.cpp | 51 +- .../PVTFunctions/BrineViscosityFunction.hpp | 116 ++- .../PVTFunctions/CO2SolubilityFunction.cpp | 414 ++++---- .../PVTFunctions/CO2SolubilityFunction.hpp | 273 +++++- .../FenghourCO2ViscosityFunction.cpp | 166 ++-- .../FenghourCO2ViscosityFunction.hpp | 125 ++- .../fluid/PVTFunctions/FlashModelBase.hpp | 101 +- .../NewBrineCO2DensityFunction.cpp | 175 ---- .../NewBrineCO2DensityFunction.hpp | 229 ----- .../NewBrineViscosityFunction.cpp | 78 -- .../NewBrineViscosityFunction.hpp | 142 --- .../PVTFunctions/NewCO2SolubilityFunction.cpp | 344 ------- .../PVTFunctions/NewCO2SolubilityFunction.hpp | 298 ------ .../NewFenghourCO2ViscosityFunction.cpp | 164 ---- .../NewFenghourCO2ViscosityFunction.hpp | 148 --- .../fluid/PVTFunctions/NewFlashModelBase.hpp | 124 --- .../fluid/PVTFunctions/NewPVTFunctionBase.hpp | 124 --- .../NewSpanWagnerCO2DensityFunction.cpp | 321 ------- .../NewSpanWagnerCO2DensityFunction.hpp | 165 ---- .../fluid/PVTFunctions/PVTFunctionBase.hpp | 99 +- .../SpanWagnerCO2DensityFunction.cpp | 243 ++--- .../SpanWagnerCO2DensityFunction.hpp | 134 ++- .../fluid/PVTFunctions/UtilityFunctions.cpp | 128 --- .../fluid/PVTFunctions/UtilityFunctions.hpp | 549 ----------- .../constitutive/fluid/multiFluidSelector.hpp | 7 +- .../unitTests/testCO2BrinePVTModels.cpp | 260 +++-- .../constitutive/unitTests/testMultiFluid.cpp | 215 +++-- .../fileIO/schema/docs/Constitutive.rst | 1 - .../fileIO/schema/docs/Constitutive_other.rst | 1 - .../docs/MultiPhaseMultiComponentFluid.rst | 20 +- src/coreComponents/fileIO/schema/schema.xsd | 15 - .../fileIO/schema/schema.xsd.other | 53 -- .../fluidFlow/CompositionalMultiphaseBase.cpp | 52 +- .../CompositionalMultiphaseBaseKernels.hpp | 8 +- .../fluidFlow/CompositionalMultiphaseFVM.cpp | 32 +- .../wells/CompositionalMultiphaseWell.cpp | 18 +- src/docs/sphinx/CompleteXMLSchema.rst | 14 - 49 files changed, 2390 insertions(+), 5568 deletions(-) delete mode 100644 src/coreComponents/constitutive/fluid/NewMultiPhaseMultiComponentFluid.cpp delete mode 100644 src/coreComponents/constitutive/fluid/NewMultiPhaseMultiComponentFluid.hpp delete mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.cpp delete mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.hpp delete mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.cpp delete mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.hpp delete mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.cpp delete mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.hpp delete mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.cpp delete mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.hpp delete mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewFlashModelBase.hpp delete mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewPVTFunctionBase.hpp delete mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.cpp delete mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.hpp delete mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/UtilityFunctions.cpp delete mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/UtilityFunctions.hpp diff --git a/src/coreComponents/constitutive/CMakeLists.txt b/src/coreComponents/constitutive/CMakeLists.txt index b4959a6fb7e..d7b10ee21e2 100644 --- a/src/coreComponents/constitutive/CMakeLists.txt +++ b/src/coreComponents/constitutive/CMakeLists.txt @@ -14,22 +14,13 @@ set( constitutive_headers contact/ContactRelationBase.hpp contact/Coulomb.hpp fluid/MultiPhaseMultiComponentFluid.hpp - fluid/NewMultiPhaseMultiComponentFluid.hpp fluid/PVTFunctions/BrineCO2DensityFunction.hpp - fluid/PVTFunctions/NewBrineCO2DensityFunction.hpp fluid/PVTFunctions/BrineViscosityFunction.hpp - fluid/PVTFunctions/NewBrineViscosityFunction.hpp fluid/PVTFunctions/CO2SolubilityFunction.hpp - fluid/PVTFunctions/NewCO2SolubilityFunction.hpp fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp - fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.hpp fluid/PVTFunctions/FlashModelBase.hpp - fluid/PVTFunctions/NewFlashModelBase.hpp fluid/PVTFunctions/PVTFunctionBase.hpp - fluid/PVTFunctions/NewPVTFunctionBase.hpp fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp - fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.hpp - fluid/PVTFunctions/UtilityFunctions.hpp fluid/SingleFluidBase.hpp fluid/singleFluidSelector.hpp fluid/MultiFluidBase.hpp @@ -82,18 +73,11 @@ set( constitutive_sources contact/Coulomb.cpp fluid/CompressibleSinglePhaseFluid.cpp fluid/MultiPhaseMultiComponentFluid.cpp - fluid/NewMultiPhaseMultiComponentFluid.cpp fluid/PVTFunctions/BrineCO2DensityFunction.cpp - fluid/PVTFunctions/NewBrineCO2DensityFunction.cpp fluid/PVTFunctions/BrineViscosityFunction.cpp - fluid/PVTFunctions/NewBrineViscosityFunction.cpp fluid/PVTFunctions/CO2SolubilityFunction.cpp - fluid/PVTFunctions/NewCO2SolubilityFunction.cpp fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp - fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.cpp fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp - fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.cpp - fluid/PVTFunctions/UtilityFunctions.cpp fluid/SingleFluidBase.cpp fluid/MultiFluidBase.cpp fluid/CompressibleSinglePhaseFluid.cpp diff --git a/src/coreComponents/constitutive/fluid/BlackOilFluid.hpp b/src/coreComponents/constitutive/fluid/BlackOilFluid.hpp index bd51d5d1cac..04630e106d6 100644 --- a/src/coreComponents/constitutive/fluid/BlackOilFluid.hpp +++ b/src/coreComponents/constitutive/fluid/BlackOilFluid.hpp @@ -32,6 +32,8 @@ class BlackOilFluid : public MultiFluidPVTPackageWrapper { public: + using exec_policy = serialPolicy; + enum class FluidType : integer { DeadOil, diff --git a/src/coreComponents/constitutive/fluid/CompositionalMultiphaseFluid.hpp b/src/coreComponents/constitutive/fluid/CompositionalMultiphaseFluid.hpp index a6dd000e22c..3abac7b4b32 100644 --- a/src/coreComponents/constitutive/fluid/CompositionalMultiphaseFluid.hpp +++ b/src/coreComponents/constitutive/fluid/CompositionalMultiphaseFluid.hpp @@ -30,6 +30,8 @@ class CompositionalMultiphaseFluid : public MultiFluidPVTPackageWrapper { public: + using exec_policy = serialPolicy; + CompositionalMultiphaseFluid( string const & name, Group * const parent ); virtual ~CompositionalMultiphaseFluid() override; diff --git a/src/coreComponents/constitutive/fluid/MultiFluidBase.hpp b/src/coreComponents/constitutive/fluid/MultiFluidBase.hpp index 7518d30c4e5..68bf732cdb6 100644 --- a/src/coreComponents/constitutive/fluid/MultiFluidBase.hpp +++ b/src/coreComponents/constitutive/fluid/MultiFluidBase.hpp @@ -163,6 +163,7 @@ class MultiFluidBaseUpdate private: + GEOSX_HOST_DEVICE virtual void compute( real64 const pressure, real64 const temperature, arraySlice1d< real64 const > const & composition, @@ -173,6 +174,7 @@ class MultiFluidBaseUpdate arraySlice2d< real64 > const & phaseCompFraction, real64 & totalDensity ) const = 0; + GEOSX_HOST_DEVICE virtual void compute( real64 const pressure, real64 const temperature, arraySlice1d< real64 const > const & composition, @@ -201,12 +203,12 @@ class MultiFluidBaseUpdate real64 & dTotalDensity_dTemperature, arraySlice1d< real64 > const & dTotalDensity_dGlobalCompFraction ) const = 0; + GEOSX_HOST_DEVICE virtual void update( localIndex const k, localIndex const q, real64 const pressure, real64 const temperature, arraySlice1d< real64 const > const & composition ) const = 0; - }; class MultiFluidBase : public ConstitutiveBase diff --git a/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.cpp b/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.cpp index ab1f7404ad9..05c702f6b09 100644 --- a/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.cpp +++ b/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.cpp @@ -81,6 +81,7 @@ MultiFluidPVTPackageWrapper::deliverClone( string const & name, return clone; } +GEOSX_HOST_DEVICE void MultiFluidPVTPackageWrapperUpdate::compute( real64 pressure, real64 temperature, arraySlice1d< real64 const, 0 > const & composition, @@ -91,6 +92,7 @@ void MultiFluidPVTPackageWrapperUpdate::compute( real64 pressure, arraySlice2d< real64, 1 > const & phaseCompFrac, real64 & totalDens ) const { +#ifndef __CUDACC__ localIndex const NC = m_componentMolarWeight.size(); localIndex const NP = m_phaseTypes.size(); @@ -195,8 +197,10 @@ void MultiFluidPVTPackageWrapperUpdate::compute( real64 pressure, // 5.2. Invert the previous quantity to get actual density totalDens = 1.0 / totalDens; } +#endif } +GEOSX_HOST_DEVICE void MultiFluidPVTPackageWrapperUpdate::compute( real64 pressure, real64 temperature, arraySlice1d< real64 const, 0 > const & composition, @@ -225,6 +229,7 @@ void MultiFluidPVTPackageWrapperUpdate::compute( real64 pressure, real64 & dTotalDensity_dTemperature, arraySlice1d< real64, 0 > const & dTotalDensity_dGlobalCompFraction ) const { +#ifndef __CUDACC__ // 0. make shortcut structs to avoid long names (TODO maybe remove) CompositionalVarContainer< 1 > phaseFrac{ phaseFraction, @@ -268,11 +273,6 @@ void MultiFluidPVTPackageWrapperUpdate::compute( real64 pressure, dTotalDensity_dGlobalCompFraction }; -#if defined(__CUDACC__) - // For some reason nvcc thinks these aren't used. - GEOSX_UNUSED_VAR( phaseFrac, phaseDens, phaseMassDens, phaseVisc, phaseCompFrac, totalDens ); -#endif - localIndex constexpr maxNumComp = MultiFluidBase::MAX_NUM_COMPONENTS; localIndex const NC = numComponents(); localIndex const NP = numPhases(); @@ -489,6 +489,7 @@ void MultiFluidPVTPackageWrapperUpdate::compute( real64 pressure, totalDens.dComp[jc] *= minusDens2; } } +#endif } } //namespace constitutive diff --git a/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.hpp b/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.hpp index 6d34e357485..6708fc77ede 100644 --- a/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.hpp +++ b/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.hpp @@ -117,6 +117,7 @@ class MultiFluidPVTPackageWrapperUpdate final : public MultiFluidBaseUpdate /// Deleted move assignment operator MultiFluidPVTPackageWrapperUpdate & operator=( MultiFluidPVTPackageWrapperUpdate && ) = delete; + GEOSX_HOST_DEVICE virtual void compute( real64 const pressure, real64 const temperature, arraySlice1d< real64 const > const & composition, @@ -127,6 +128,7 @@ class MultiFluidPVTPackageWrapperUpdate final : public MultiFluidBaseUpdate arraySlice2d< real64 > const & phaseCompFraction, real64 & totalDensity ) const override; + GEOSX_HOST_DEVICE virtual void compute( real64 const pressure, real64 const temperature, arraySlice1d< real64 const > const & composition, @@ -155,6 +157,7 @@ class MultiFluidPVTPackageWrapperUpdate final : public MultiFluidBaseUpdate real64 & dTotalDensity_dTemperature, arraySlice1d< real64 > const & dTotalDensity_dGlobalCompFraction ) const override; + GEOSX_HOST_DEVICE GEOSX_FORCE_INLINE virtual void update( localIndex const k, localIndex const q, @@ -162,6 +165,7 @@ class MultiFluidPVTPackageWrapperUpdate final : public MultiFluidBaseUpdate real64 const temperature, arraySlice1d< real64 const > const & composition ) const override { +#ifndef __CUDACC__ compute( pressure, temperature, composition, @@ -189,6 +193,7 @@ class MultiFluidPVTPackageWrapperUpdate final : public MultiFluidBaseUpdate m_dTotalDensity_dPressure[k][q], m_dTotalDensity_dTemperature[k][q], m_dTotalDensity_dGlobalCompFraction[k][q] ); +#endif } private: diff --git a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp index 73afe2f7049..dfe8752c383 100644 --- a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp +++ b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp @@ -19,10 +19,6 @@ #include "common/Path.hpp" #include "managers/ProblemManager.hpp" -#include "constitutive/fluid/MultiFluidUtils.hpp" -#include "PVTFunctions/FlashModelBase.hpp" -#include "PVTFunctions/PVTFunctionBase.hpp" - namespace geosx { @@ -37,17 +33,15 @@ namespace constitutive MultiPhaseMultiComponentFluid::MultiPhaseMultiComponentFluid( string const & name, Group * const parent ): MultiFluidBase( name, parent ) { - registerWrapper( viewKeyStruct::phasePVTParaFilesString(), &m_phasePVTParaFiles ). setInputFlag( InputFlags::REQUIRED ). setRestartFlags( RestartFlags::NO_WRITE ). - setDescription( "List of the names of the files including PVT function parameters" ); + setDescription( "Names of the files defining the parameters of the viscosity and density models" ); registerWrapper( viewKeyStruct::flashModelParaFileString(), &m_flashModelParaFile ). setInputFlag( InputFlags::REQUIRED ). setRestartFlags( RestartFlags::NO_WRITE ). - setDescription( "name of the filen including flash calculation function parameters" ); - + setDescription( "Name of the file defining the parameters of the flash model" ); } MultiPhaseMultiComponentFluid::~MultiPhaseMultiComponentFluid() @@ -61,25 +55,10 @@ MultiPhaseMultiComponentFluid::deliverClone( string const & name, std::unique_ptr< ConstitutiveBase > clone = MultiFluidBase::deliverClone( name, parent ); MultiPhaseMultiComponentFluid * const newConstitutiveRelation = dynamic_cast< MultiPhaseMultiComponentFluid * >(clone.get()); + newConstitutiveRelation->m_phaseGasIndex = this->m_phaseGasIndex; + newConstitutiveRelation->m_phaseLiquidIndex = this->m_phaseLiquidIndex; - - newConstitutiveRelation->m_useMass = this->m_useMass; - - newConstitutiveRelation->m_componentNames = this->m_componentNames; - newConstitutiveRelation->m_componentMolarWeight = this->m_componentMolarWeight; - - newConstitutiveRelation->m_phaseNames = this->m_phaseNames; - - newConstitutiveRelation->m_phasePVTParaFiles = this->m_phasePVTParaFiles; - - newConstitutiveRelation->m_flashModelParaFile = this->m_flashModelParaFile; - - // newConstitutiveRelation->CreatePVTModels(); - - newConstitutiveRelation->m_phaseDensityFuns = this->m_phaseDensityFuns; - newConstitutiveRelation->m_phaseViscosityFuns = this->m_phaseViscosityFuns; - - newConstitutiveRelation->m_flashModel = this->m_flashModel; + newConstitutiveRelation->createPVTModels(); return clone; } @@ -88,351 +67,120 @@ void MultiPhaseMultiComponentFluid::postProcessInput() { MultiFluidBase::postProcessInput(); - localIndex const NP = numFluidPhases(); - - GEOSX_ERROR_IF( m_phasePVTParaFiles.size() != NP, "The number of phasePVTParaFiles is not the same as the number of phases!" ); + localIndex const numPhases = numFluidPhases(); + localIndex const numComps = numFluidComponents(); + GEOSX_ERROR_IF( numPhases != 2, "The number of phases in this model should be equal to 2" ); + GEOSX_ERROR_IF( numComps != 2, "The number of components in this model should be equal to 2" ); + GEOSX_ERROR_IF( m_phasePVTParaFiles.size() != 2, "The number of phasePVTParaFiles is not the same as the number of phases!" ); - createPVTModels(); - -} - -void MultiPhaseMultiComponentFluid::initializePostSubGroups() -{ - MultiFluidBase::initializePostSubGroups(); + bool notFound = true; + for( localIndex i = 0; i < m_phaseNames.size(); ++i ) + { + if( m_phaseNames[i] == "CO2" || m_phaseNames[i] == "co2" || + m_phaseNames[i] == "gas" || m_phaseNames[i] == "Gas" ) + { + m_phaseGasIndex = i; + notFound = false; + break; + } + } + GEOSX_ERROR_IF( notFound, "Phase co2/gas is not found!" ); - // CreatePVTModels(); + notFound = true; + for( localIndex i = 0; i < m_phaseNames.size(); ++i ) + { + if( m_phaseNames[i] == "Water" || m_phaseNames[i] == "water" || + m_phaseNames[i] == "Liquid" || m_phaseNames[i] == "liquid" ) + { + m_phaseLiquidIndex = i; + notFound = false; + break; + } + } + GEOSX_ERROR_IF( notFound, "Phase water/liquid is not found!" ); + createPVTModels(); } - void MultiPhaseMultiComponentFluid::createPVTModels() { - for( string & filename : m_phasePVTParaFiles ) + // 1) Create the viscosity and density models + for( string const & filename : m_phasePVTParaFiles ) { std::ifstream is( filename ); - constexpr std::streamsize buf_size = 256; char buf[buf_size]; - while( is.getline( buf, buf_size )) + while( is.getline( buf, buf_size ) ) { string const str( buf ); string_array const strs = Tokenize( str, " " ); - if( strs[0] == "DensityFun" ) { - m_phaseDensityFuns.emplace_back( PVTFunction::CatalogInterface::factory( strs[ 1 ], - strs, - m_componentNames, - m_componentMolarWeight ) ); + if( strs[1] == "SpanWagnerCO2Density" ) + { + m_co2Density = std::make_unique< SpanWagnerCO2Density >( strs, m_componentNames, m_componentMolarWeight ); + m_co2DensityWrapper.emplace_back( m_co2Density->createKernelWrapper() ); + } + else if( strs[1] == "BrineCO2Density" ) + { + m_brineDensity = std::make_unique< BrineCO2Density >( strs, m_componentNames, m_componentMolarWeight ); + m_brineDensityWrapper.emplace_back( m_brineDensity->createKernelWrapper() ); + } } else if( strs[0] == "ViscosityFun" ) { - m_phaseViscosityFuns.emplace_back( PVTFunction::CatalogInterface::factory( strs[ 1 ], - strs, - m_componentNames, - m_componentMolarWeight ) ); + if( strs[1] == "FenghourCO2Viscosity" ) + { + m_co2Viscosity = std::make_unique< FenghourCO2Viscosity >( strs, m_componentNames, m_componentMolarWeight ); + m_co2ViscosityWrapper.emplace_back( m_co2Viscosity->createKernelWrapper() ); + } + else if( strs[1] == "BrineViscosity" ) + { + m_brineViscosity = std::make_unique< BrineViscosity >( strs, m_componentNames, m_componentMolarWeight ); + m_brineViscosityWrapper.emplace_back( m_brineViscosity->createKernelWrapper() ); + } } else { GEOSX_ERROR( "Error: Invalid PVT function: " << strs[0] << "." ); } } - is.close(); } + GEOSX_ERROR_IF( m_co2Density == nullptr, "SpanWagnerCO2Density model not found" ); + GEOSX_ERROR_IF( m_brineDensity == nullptr, "BrineCO2Density model not found" ); + GEOSX_ERROR_IF( m_co2Viscosity == nullptr, "FenghourCO2Viscosity model not found" ); + GEOSX_ERROR_IF( m_brineViscosity == nullptr, "BrineViscosity model not found" ); + + // 2) Create the flash model { std::ifstream is( m_flashModelParaFile ); - constexpr std::streamsize buf_size = 256; char buf[buf_size]; - while( is.getline( buf, buf_size )) + while( is.getline( buf, buf_size ) ) { string const str( buf ); string_array const strs = Tokenize( str, " " ); - - if( strs[0] == "FlashModel" ) + if( strs[0] == "FlashModel" && strs[1] == "CO2Solubility" ) { - m_flashModel = FlashModel::CatalogInterface::factory( strs[1], - strs, - m_phaseNames, - m_componentNames, - m_componentMolarWeight ); + m_co2Solubility = std::make_unique< CO2Solubility >( strs, m_phaseNames, m_componentNames, m_componentMolarWeight ); + m_co2SolubilityWrapper.emplace_back( m_co2Solubility->createKernelWrapper() ); } else { - GEOSX_ERROR( "Error: Not flash model: " << strs[0] << "." ); + GEOSX_ERROR( "Error: Invalid flash model: " << strs[0] << ", " << strs[1] << "." ); } } - is.close(); } -} - -REGISTER_CATALOG_ENTRY( ConstitutiveBase, MultiPhaseMultiComponentFluid, string const &, Group * const ) -void MultiPhaseMultiComponentFluidUpdate::compute( real64 pressure, - real64 temperature, - arraySlice1d< real64 const > const & composition, - arraySlice1d< real64 > const & phaseFraction, - arraySlice1d< real64 > const & phaseDensity, - arraySlice1d< real64 > const & phaseMassDensity, - arraySlice1d< real64 > const & phaseViscosity, - arraySlice2d< real64 > const & phaseCompFraction, - real64 & totalDensity ) const -{ - GEOSX_UNUSED_VAR( pressure ) - GEOSX_UNUSED_VAR( temperature ) - GEOSX_UNUSED_VAR( composition ) - GEOSX_UNUSED_VAR( phaseFraction ) - GEOSX_UNUSED_VAR( phaseDensity ) - GEOSX_UNUSED_VAR( phaseMassDensity ) - GEOSX_UNUSED_VAR( phaseViscosity ) - GEOSX_UNUSED_VAR( phaseCompFraction ) - GEOSX_UNUSED_VAR( totalDensity ) - GEOSX_ERROR( "Not implemented" ); + GEOSX_ERROR_IF( m_co2Solubility == nullptr, "CO2Solubility model not found" ); } -void MultiPhaseMultiComponentFluidUpdate::compute( real64 pressure, - real64 temperature, - arraySlice1d< real64 const > const & composition, - arraySlice1d< real64 > const & phaseFraction, - arraySlice1d< real64 > const & dPhaseFraction_dPressure, - arraySlice1d< real64 > const & dPhaseFraction_dTemperature, - arraySlice2d< real64 > const & dPhaseFraction_dGlobalCompFraction, - arraySlice1d< real64 > const & phaseDensity, - arraySlice1d< real64 > const & dPhaseDensity_dPressure, - arraySlice1d< real64 > const & dPhaseDensity_dTemperature, - arraySlice2d< real64 > const & dPhaseDensity_dGlobalCompFraction, - arraySlice1d< real64 > const & phaseMassDensity, - arraySlice1d< real64 > const & dPhaseMassDensity_dPressure, - arraySlice1d< real64 > const & dPhaseMassDensity_dTemperature, - arraySlice2d< real64 > const & dPhaseMassDensity_dGlobalCompFraction, - arraySlice1d< real64 > const & phaseViscosity, - arraySlice1d< real64 > const & dPhaseViscosity_dPressure, - arraySlice1d< real64 > const & dPhaseViscosity_dTemperature, - arraySlice2d< real64 > const & dPhaseViscosity_dGlobalCompFraction, - arraySlice2d< real64 > const & phaseCompFraction, - arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, - arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, - arraySlice3d< real64 > const & dPhaseCompFraction_dGlobalCompFraction, - real64 & totalDensity, - real64 & dTotalDensity_dPressure, - real64 & dTotalDensity_dTemperature, - arraySlice1d< real64 > const & dTotalDensity_dGlobalCompFraction ) const -{ - CompositionalVarContainer< 1 > phaseFrac { - phaseFraction, - dPhaseFraction_dPressure, - dPhaseFraction_dTemperature, - dPhaseFraction_dGlobalCompFraction - }; - - CompositionalVarContainer< 1 > phaseDens { - phaseDensity, - dPhaseDensity_dPressure, - dPhaseDensity_dTemperature, - dPhaseDensity_dGlobalCompFraction - }; - - CompositionalVarContainer< 1 > phaseMassDens { - phaseMassDensity, - dPhaseMassDensity_dPressure, - dPhaseMassDensity_dTemperature, - dPhaseMassDensity_dGlobalCompFraction - }; - - CompositionalVarContainer< 1 > phaseVisc { - phaseViscosity, - dPhaseViscosity_dPressure, - dPhaseViscosity_dTemperature, - dPhaseViscosity_dGlobalCompFraction - }; - - CompositionalVarContainer< 2 > phaseCompFrac { - phaseCompFraction, - dPhaseCompFraction_dPressure, - dPhaseCompFraction_dTemperature, - dPhaseCompFraction_dGlobalCompFraction - }; - - CompositionalVarContainer< 0 > totalDens { - totalDensity, - dTotalDensity_dPressure, - dTotalDensity_dTemperature, - dTotalDensity_dGlobalCompFraction - }; - -#if defined(__CUDACC__) - // For some reason nvcc thinks these aren't used. - GEOSX_UNUSED_VAR( phaseFrac, phaseDens, phaseMassDens, phaseVisc, phaseCompFrac, totalDens ); -#endif - - localIndex constexpr maxNumComp = MultiFluidBase::MAX_NUM_COMPONENTS; - localIndex constexpr maxNumPhase = MultiFluidBase::MAX_NUM_PHASES; - localIndex const NC = numComponents(); - localIndex const NP = numPhases(); - - stackArray1d< EvalVarArgs, maxNumComp > C( NC ); - - if( m_useMass ) - { - stackArray1d< EvalVarArgs, maxNumComp > X( NC ); - EvalVarArgs totalMolality = 0.0; - for( localIndex ic = 0; ic < NC; ++ic ) - { - X[ic].m_var = composition[ic]; - X[ic].m_der[ic+1] = 1.0; - - real64 const mwInv = 1.0 / m_componentMolarWeight[ic]; - C[ic] = X[ic] * mwInv; // this is molality (units of mole/mass) - totalMolality += C[ic]; - } - - for( localIndex ic = 0; ic < NC; ++ic ) - { - C[ic] /= totalMolality; - } - } - else - { - for( localIndex ic = 0; ic < NC; ++ic ) - { - C[ic].m_var = composition[ic]; - C[ic].m_der[ic+1] = 1.0; - } - } - - EvalVarArgs P = pressure; - P.m_der[0] = 1.0; - - constexpr real64 TK = 273.15; - EvalVarArgs T = temperature - TK; - - stackArray1d< EvalVarArgs, maxNumPhase > phaseFractionTemp( NP ); - stackArray2d< EvalVarArgs, maxNumPhase * maxNumComp > phaseCompFractionTemp( NP, NC ); - - //phaseFractionTemp and phaseCompFractionTemp all are mole fraction, - //w.r.t mole fraction or mass fraction (useMass) - m_flashModel->partition( P, T, C, phaseFractionTemp, phaseCompFractionTemp ); - - stackArray1d< EvalVarArgs, maxNumPhase > phaseDensityTemp( NP ); - stackArray1d< EvalVarArgs, maxNumPhase > phaseMassDensityTemp( NP ); - stackArray1d< EvalVarArgs, maxNumPhase > phaseViscosityTemp( NP ); - - for( localIndex ip = 0; ip < NP; ++ip ) - { - // molarDensity or massDensity (useMass) - m_phaseDensityFuns[ip]->evaluation( P, T, phaseCompFractionTemp[ip], phaseDensityTemp[ip], m_useMass ); - m_phaseViscosityFuns[ip]->evaluation( P, T, phaseCompFractionTemp[ip], phaseViscosityTemp[ip] ); - } - - if( m_useMass ) - { - stackArray1d< EvalVarArgs, maxNumPhase > phaseMW( NP ); - for( localIndex ip = 0; ip < NP; ++ip ) - { - // copy phaseDens into phaseMassDens - phaseMassDensityTemp[ip] = phaseDensityTemp[ip]; - - // compute the molecular weight to get the mass phase (component) fractions - EvalVarArgs molarDens; - m_phaseDensityFuns[ip]->evaluation( P, T, phaseCompFractionTemp[ip], molarDens, 0 ); - phaseMW[ip] = phaseDensityTemp[ip] / molarDens; - } - - EvalVarArgs totalMass = 0.0; - for( localIndex ip = 0; ip < NP; ++ip ) - { - phaseFractionTemp[ip] *= phaseMW[ip]; - totalMass += phaseFractionTemp[ip]; - } - - for( localIndex ip = 0; ip < NP; ++ip ) - { - phaseFractionTemp[ip] /= totalMass; - } - - for( localIndex ip = 0; ip < NP; ++ip ) - { - for( localIndex ic = 0; ic < NC; ++ic ) - { - - real64 compMW = m_componentMolarWeight[ic]; - - phaseCompFractionTemp[ip][ic] = phaseCompFractionTemp[ip][ic] * compMW / phaseMW[ip]; - - } - } - } - else - { - for( localIndex ip = 0; ip < NP; ++ip ) - { - // recompute the mass density - EvalVarArgs massDens; - m_phaseDensityFuns[ip]->evaluation( P, T, phaseCompFractionTemp[ip], massDens, 1 ); - - // copy phaseDens into phaseMassDens - phaseMassDensityTemp[ip] = massDens; - } - } - - EvalVarArgs totalDensityTemp = 0.0; - for( localIndex ip = 0; ip < NP; ++ip ) - { - totalDensityTemp += phaseFractionTemp[ip] / phaseDensityTemp[ip]; - } - totalDensityTemp = 1.0 / totalDensityTemp; - - //transfer data - for( localIndex ip = 0; ip < NP; ++ip ) - { - phaseFrac.value[ip] = phaseFractionTemp[ip].m_var; - phaseFrac.dPres[ip] = phaseFractionTemp[ip].m_der[0]; - phaseFrac.dTemp[ip] = 0.0; - - phaseDens.value[ip] = phaseDensityTemp[ip].m_var; - phaseDens.dPres[ip] = phaseDensityTemp[ip].m_der[0]; - phaseDens.dTemp[ip] = 0.0; - - phaseMassDens.value[ip] = phaseMassDensityTemp[ip].m_var; - phaseMassDens.dPres[ip] = phaseMassDensityTemp[ip].m_der[0]; - phaseMassDens.dTemp[ip] = 0.0; - - phaseVisc.value[ip] = phaseViscosityTemp[ip].m_var; - phaseVisc.dPres[ip] = phaseViscosityTemp[ip].m_der[0]; - phaseVisc.dTemp[ip] = 0.0; - - for( localIndex ic = 0; ic < NC; ++ic ) - { - phaseFrac.dComp[ip][ic] = phaseFractionTemp[ip].m_der[ic+1]; - phaseDens.dComp[ip][ic] = phaseDensityTemp[ip].m_der[ic+1]; - phaseMassDens.dComp[ip][ic] = phaseMassDensityTemp[ip].m_der[ic+1]; - phaseVisc.dComp[ip][ic] = phaseViscosityTemp[ip].m_der[ic+1]; - - phaseCompFrac.value[ip][ic] = phaseCompFractionTemp[ip][ic].m_var; - phaseCompFrac.dPres[ip][ic] = phaseCompFractionTemp[ip][ic].m_der[0]; - phaseCompFrac.dTemp[ip][ic] = 0.0; - - for( localIndex jc = 0; jc < NC; ++jc ) - { - phaseCompFrac.dComp[ip][ic][jc] = phaseCompFractionTemp[ip][ic].m_der[jc+1]; - } - } - } - - totalDens.value = totalDensityTemp.m_var; - totalDens.dPres = totalDensityTemp.m_der[0]; - totalDens.dTemp = 0.0; - - for( localIndex ic = 0; ic < NC; ++ic ) - { - totalDens.dComp[ic] = totalDensityTemp.m_der[ic+1]; - } -} +REGISTER_CATALOG_ENTRY( ConstitutiveBase, MultiPhaseMultiComponentFluid, string const &, Group * const ) } //namespace constitutive diff --git a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp index f91e5c48830..212eb20eaa0 100644 --- a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp +++ b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp @@ -20,41 +20,35 @@ #define GEOSX_CONSTITUTIVE_FLUID_MULTIPHASEMULTICOMPONENTFLUID_HPP_ #include "constitutive/fluid/MultiFluidBase.hpp" +#include "constitutive/fluid/MultiFluidUtils.hpp" +#include "PVTFunctions/BrineCO2DensityFunction.hpp" +#include "PVTFunctions/SpanWagnerCO2DensityFunction.hpp" +#include "PVTFunctions/BrineViscosityFunction.hpp" +#include "PVTFunctions/FenghourCO2ViscosityFunction.hpp" +#include "PVTFunctions/CO2SolubilityFunction.hpp" #include - namespace geosx { -namespace dataRepository -{ -namespace keys -{ -string const multiPhaseMultiComponentFluid = "MultiPhaseMultiComponentFluid"; -} -} - -namespace PVTProps -{ -class PVTFunction; -class FlashModel; -} - namespace constitutive { /** * @brief Kernel wrapper class for MultiPhaseMultiComponentFluid. - * @note Not thread-safe, do not use with any parallel launch policy. */ class MultiPhaseMultiComponentFluidUpdate final : public MultiFluidBaseUpdate { public: - MultiPhaseMultiComponentFluidUpdate( std::vector< std::shared_ptr< PVTProps::PVTFunction const > > const & phaseDensityFuns, - std::vector< std::shared_ptr< PVTProps::PVTFunction const > > const & phaseViscosityFuns, - std::shared_ptr< PVTProps::FlashModel const > const & flashModel, + MultiPhaseMultiComponentFluidUpdate( localIndex const phaseGasIndex, + localIndex const phaseLiquidIndex, + arrayView1d< PVTProps::BrineViscosity::KernelWrapper const > const & brineViscosityWrapper, + arrayView1d< PVTProps::FenghourCO2Viscosity::KernelWrapper const > const & co2ViscosityWrapper, + arrayView1d< PVTProps::BrineCO2Density::KernelWrapper const > const & brineDensityWrapper, + arrayView1d< PVTProps::SpanWagnerCO2Density::KernelWrapper const > const & co2DensityWrapper, + arrayView1d< PVTProps::CO2Solubility::KernelWrapper const > const & co2SolubilityWrapper, arrayView1d< real64 const > const & componentMolarWeight, bool useMass, arrayView3d< real64 > const & phaseFraction, @@ -107,9 +101,13 @@ class MultiPhaseMultiComponentFluidUpdate final : public MultiFluidBaseUpdate dTotalDensity_dPressure, dTotalDensity_dTemperature, dTotalDensity_dGlobalCompFraction ), - m_phaseDensityFuns( phaseDensityFuns ), - m_phaseViscosityFuns( phaseViscosityFuns ), - m_flashModel( flashModel ) + m_phaseGasIndex( phaseGasIndex ), + m_phaseLiquidIndex( phaseLiquidIndex ), + m_brineViscosityWrapper( brineViscosityWrapper ), + m_co2ViscosityWrapper( co2ViscosityWrapper ), + m_brineDensityWrapper( brineDensityWrapper ), + m_co2DensityWrapper( co2DensityWrapper ), + m_co2SolubilityWrapper( co2SolubilityWrapper ) {} /// Default copy constructor @@ -124,6 +122,8 @@ class MultiPhaseMultiComponentFluidUpdate final : public MultiFluidBaseUpdate /// Deleted move assignment operator MultiPhaseMultiComponentFluidUpdate & operator=( MultiPhaseMultiComponentFluidUpdate && ) = delete; + GEOSX_HOST_DEVICE + GEOSX_FORCE_INLINE virtual void compute( real64 const pressure, real64 const temperature, arraySlice1d< real64 const > const & composition, @@ -134,6 +134,8 @@ class MultiPhaseMultiComponentFluidUpdate final : public MultiFluidBaseUpdate arraySlice2d< real64 > const & phaseCompFraction, real64 & totalDensity ) const override; + GEOSX_HOST_DEVICE + GEOSX_FORCE_INLINE virtual void compute( real64 const pressure, real64 const temperature, arraySlice1d< real64 const > const & composition, @@ -162,6 +164,7 @@ class MultiPhaseMultiComponentFluidUpdate final : public MultiFluidBaseUpdate real64 & dTotalDensity_dTemperature, arraySlice1d< real64 > const & dTotalDensity_dGlobalCompFraction ) const override; + GEOSX_HOST_DEVICE GEOSX_FORCE_INLINE virtual void update( localIndex const k, localIndex const q, @@ -200,16 +203,34 @@ class MultiPhaseMultiComponentFluidUpdate final : public MultiFluidBaseUpdate private: - std::vector< std::shared_ptr< PVTProps::PVTFunction const > > m_phaseDensityFuns; - std::vector< std::shared_ptr< PVTProps::PVTFunction const > > m_phaseViscosityFuns; - std::shared_ptr< PVTProps::FlashModel const > m_flashModel; + /// Index of the gas phase + localIndex const m_phaseGasIndex; + + /// Index of the liquid phase + localIndex const m_phaseLiquidIndex; + + /// Kernel wrapper for brine viscosity updates + arrayView1d< PVTProps::BrineViscosity::KernelWrapper const > const m_brineViscosityWrapper; + + /// Kernel wrapper for CO2 viscosity updates + arrayView1d< PVTProps::FenghourCO2Viscosity::KernelWrapper const > const m_co2ViscosityWrapper; + + /// Kernel wrapper for brine density updates + arrayView1d< PVTProps::BrineCO2Density::KernelWrapper const > const m_brineDensityWrapper; + /// Kernel wrapper for CO2 density updates + arrayView1d< PVTProps::SpanWagnerCO2Density::KernelWrapper const > const m_co2DensityWrapper; + + /// Kernel wrapper for phase fraction and phase component fraction updates + arrayView1d< PVTProps::CO2Solubility::KernelWrapper const > const m_co2SolubilityWrapper; }; class MultiPhaseMultiComponentFluid : public MultiFluidBase { public: + using exec_policy = parallelDevicePolicy<>; + MultiPhaseMultiComponentFluid( string const & name, Group * const parent ); virtual ~MultiPhaseMultiComponentFluid() override; @@ -219,7 +240,7 @@ class MultiPhaseMultiComponentFluid : public MultiFluidBase Group * const parent ) const override; - static string catalogName() { return dataRepository::keys::multiPhaseMultiComponentFluid; } + static string catalogName() { return "MultiPhaseMultiComponentFluid"; } virtual string getCatalogName() const override { return catalogName(); } @@ -232,9 +253,13 @@ class MultiPhaseMultiComponentFluid : public MultiFluidBase */ KernelWrapper createKernelWrapper() { - return KernelWrapper( m_phaseDensityFuns, - m_phaseViscosityFuns, - m_flashModel, + return KernelWrapper( m_phaseGasIndex, + m_phaseLiquidIndex, + m_brineViscosityWrapper.toViewConst(), + m_co2ViscosityWrapper.toViewConst(), + m_brineDensityWrapper.toViewConst(), + m_co2DensityWrapper.toViewConst(), + m_co2SolubilityWrapper.toViewConst(), m_componentMolarWeight.toViewConst(), m_useMass, m_phaseFraction, @@ -267,31 +292,594 @@ class MultiPhaseMultiComponentFluid : public MultiFluidBase { static constexpr char const * flashModelParaFileString() { return "flashModelParaFile"; } static constexpr char const * phasePVTParaFilesString() { return "phasePVTParaFiles"; } - }; + } viewKeysMultiPhaseMultiComponentFluid; protected: - virtual void postProcessInput() override; - virtual void initializePostSubGroups() override; + virtual void postProcessInput() override; private: void createPVTModels(); - // phase PVT parameter filenames + /// Names of the files defining the viscosity and density models path_array m_phasePVTParaFiles; + /// Name of the file defining the flash model Path m_flashModelParaFile; - // number of entries corrosponds to number of phases - std::vector< std::shared_ptr< PVTProps::PVTFunction const > > m_phaseDensityFuns; - std::vector< std::shared_ptr< PVTProps::PVTFunction const > > m_phaseViscosityFuns; + /// Index of the gas phase + localIndex m_phaseGasIndex; - std::shared_ptr< PVTProps::FlashModel const > m_flashModel; + /// Index of the liquid phase + localIndex m_phaseLiquidIndex; + + // TODO: Here I hard-coded all the types to avoid the virtual calls in the compute function. + // See if there is a way to reintroduce them. If it is not possible, the class should be + // renamed because it is not "multi-phase, multi-component", but just CO2-brine. + + /// Pointer to the brine viscosity model + std::unique_ptr< PVTProps::BrineViscosity > m_brineViscosity; + + /// Pointer to the CO2 viscosity model + std::unique_ptr< PVTProps::FenghourCO2Viscosity > m_co2Viscosity; + + /// Pointer to the brine density model + std::unique_ptr< PVTProps::BrineCO2Density > m_brineDensity; + + /// Pointer to the CO2 density model + std::unique_ptr< PVTProps::SpanWagnerCO2Density > m_co2Density; + + /// Pointer to the flash model + std::unique_ptr< PVTProps::CO2Solubility > m_co2Solubility; + + /// Pointer to the brine viscosity model + array1d< PVTProps::BrineViscosity::KernelWrapper > m_brineViscosityWrapper; + + /// Pointer to the CO2 viscosity model + array1d< PVTProps::FenghourCO2Viscosity::KernelWrapper > m_co2ViscosityWrapper; + + /// Pointer to the brine density model + array1d< PVTProps::BrineCO2Density::KernelWrapper > m_brineDensityWrapper; + + /// Pointer to the CO2 density model + array1d< PVTProps::SpanWagnerCO2Density::KernelWrapper > m_co2DensityWrapper; + + /// Pointer to the flash model + array1d< PVTProps::CO2Solubility::KernelWrapper > m_co2SolubilityWrapper; }; +GEOSX_HOST_DEVICE +GEOSX_FORCE_INLINE +void MultiPhaseMultiComponentFluidUpdate::compute( real64 pressure, + real64 temperature, + arraySlice1d< real64 const > const & composition, + arraySlice1d< real64 > const & phaseFraction, + arraySlice1d< real64 > const & phaseDensity, + arraySlice1d< real64 > const & phaseMassDensity, + arraySlice1d< real64 > const & phaseViscosity, + arraySlice2d< real64 > const & phaseCompFraction, + real64 & totalDensity ) const +{ + constexpr localIndex numComps = 2; + constexpr localIndex numPhases = 2; + localIndex const ipGas = m_phaseGasIndex; + localIndex const ipLiq = m_phaseLiquidIndex; + + // for now, compute the derivatives and discard them + stackArray1d< real64, numPhases > dPhaseFrac_dPres( numPhases ); + stackArray1d< real64, numPhases > dPhaseFrac_dTemp( numPhases ); + stackArray2d< real64, numPhases *numComps > dPhaseFrac_dComp( numPhases, numComps ); + stackArray2d< real64, numPhases *numComps > dPhaseCompFrac_dPres( numPhases, numComps ); + stackArray2d< real64, numPhases *numComps > dPhaseCompFrac_dTemp( numPhases, numComps ); + stackArray3d< real64, numPhases *numComps *numComps > dPhaseCompFrac_dComp( numPhases, numComps, numComps ); + real64 dPhaseDens_dPres = 0.0; + real64 dPhaseDens_dTemp = 0.0; + stackArray1d< real64, numComps > dPhaseDens_dComp( numComps ); + real64 dPhaseMassDens_dPres = 0.0; + real64 dPhaseMassDens_dTemp = 0.0; + stackArray1d< real64, numComps > dPhaseMassDens_dComp( numComps ); + real64 dPhaseVisc_dPres = 0.0; + real64 dPhaseVisc_dTemp = 0.0; + stackArray1d< real64, numComps > dPhaseVisc_dComp( numComps ); + + // 1. Convert input mass fractions to mole fractions and keep derivatives + + stackArray1d< real64, numComps > compMoleFrac( numComps ); + if( m_useMass ) + { + real64 totalMolality = 0.0; + for( localIndex ic = 0; ic < numComps; ++ic ) + { + real64 const mwInv = 1.0 / m_componentMolarWeight[ic]; + compMoleFrac[ic] = composition[ic] * mwInv; // this is molality (units of mole/mass) + totalMolality += compMoleFrac[ic]; + } + + real64 const totalMolalityInv = 1.0 / totalMolality; + for( localIndex ic = 0; ic < numComps; ++ic ) + { + compMoleFrac[ic] *= totalMolalityInv; + } + } + else + { + for( localIndex ic = 0; ic < numComps; ++ic ) + { + compMoleFrac[ic] = composition[ic]; + } + } + + // 2. Compute phase fractions and phase component fractions + + real64 const temperatureInCelsius = temperature - 273.15; + m_co2SolubilityWrapper[0].compute( pressure, + temperatureInCelsius, + compMoleFrac, + phaseFraction, dPhaseFrac_dPres, dPhaseFrac_dTemp, dPhaseFrac_dComp, + phaseCompFraction, dPhaseCompFrac_dPres, dPhaseCompFrac_dTemp, dPhaseCompFrac_dComp ); + + // 3. Compute phase densities and phase viscosities + + m_co2DensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFraction[ipGas], + phaseDensity[ipGas], dPhaseDens_dPres, dPhaseDens_dTemp, dPhaseDens_dComp, + m_useMass ); + m_co2ViscosityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFraction[ipGas], + phaseViscosity[ipGas], dPhaseVisc_dPres, dPhaseVisc_dTemp, dPhaseVisc_dComp, + m_useMass ); + + m_brineDensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFraction[ipLiq], + phaseDensity[ipLiq], dPhaseDens_dPres, dPhaseDens_dTemp, dPhaseDens_dComp, + m_useMass ); + m_brineViscosityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFraction[ipLiq], + phaseViscosity[ipLiq], dPhaseVisc_dPres, dPhaseVisc_dTemp, dPhaseVisc_dComp, + m_useMass ); + + // 4. Depending on the m_useMass flag, convert to mass variables or simply compute mass density + + // TODO: for now the treatment of molar/mass density requires too many interpolations in the tables, it needs to be fixed + // we should modify the PVT functions so that they can return phaseMassDens, phaseDens, and phaseMW in one call + // TODO: extract the following piece of code and write a function that can be used here and in MultiFluidPVTPackageWrapper + + if( m_useMass ) + { + // 4.1. Convert phase fractions (requires two passes) + real64 totalMass{}; + + // 4.1.0. Compute the phase molecular weights (ultimately, get that from the PVT function) + real64 phaseMW[2]{}; + real64 phaseMolarDens = 0.0; + real64 dPhaseMolarDens_dPres = 0.0; + real64 dPhaseMolarDens_dTemp = 0.0; + stackArray1d< real64, numComps > dPhaseMolarDens_dComp( 2 ); + m_co2DensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFraction[ipGas], + phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, + 0 ); + phaseMW[ipGas] = phaseDensity[ipGas] / phaseMolarDens; + m_brineDensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFraction[ipLiq], + phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, + 0 ); + phaseMW[ipLiq] = phaseDensity[ipLiq] / phaseMolarDens; + + // 4.1.1. Compute mass of each phase and total mass (on a 1-mole basis) + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + phaseFraction[ip] *= phaseMW[ip]; + totalMass += phaseFraction[ip]; + } + // 4.1.2. Normalize to get mass fractions + real64 const totalMassInv = 1.0 / totalMass; + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + phaseFraction[ip] *= totalMassInv; + } + // 4.2. Convert phase compositions + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + real64 const phaseMWInv = 1.0 / phaseMW[ip]; + + for( localIndex ic = 0; ic < numComps; ++ic ) + { + real64 const compMW = m_componentMolarWeight[ic]; + phaseCompFraction[ip][ic] = phaseCompFraction[ip][ic] * compMW * phaseMWInv; + } + } + // 4.3 Copy the phase densities into the phase mass densities + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + phaseMassDensity[ip] = phaseDensity[ip]; + } + } + else + { + // for now, we have to compute the phase mass density here + m_co2DensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFraction[ipGas], + phaseMassDensity[ipGas], dPhaseMassDens_dPres, + dPhaseMassDens_dTemp, dPhaseMassDens_dComp, + true ); + m_brineDensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFraction[ipLiq], + phaseMassDensity[ipLiq], dPhaseMassDens_dPres, + dPhaseMassDens_dTemp, dPhaseMassDens_dComp, + true ); + } + + // TODO: extract the following piece of code and write a function that can be used here and in MultiFluidPVTPackageWrapper + + // 5. Compute total fluid mass/molar density and derivatives + { + totalDensity = 0.0; + // 5.1. Sum mass/molar fraction/density ratio over all phases to get the inverse of density + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + real64 const densInv = 1.0 / phaseDensity[ip]; + real64 const value = phaseFraction[ip] * densInv; + totalDensity += value; + } + // 5.2. Invert the previous quantity to get actual density + totalDensity = 1.0 / totalDensity; + } +} + +GEOSX_HOST_DEVICE +GEOSX_FORCE_INLINE +void MultiPhaseMultiComponentFluidUpdate::compute( real64 pressure, + real64 temperature, + arraySlice1d< real64 const > const & composition, + arraySlice1d< real64 > const & phaseFraction, + arraySlice1d< real64 > const & dPhaseFraction_dPressure, + arraySlice1d< real64 > const & dPhaseFraction_dTemperature, + arraySlice2d< real64 > const & dPhaseFraction_dGlobalCompFraction, + arraySlice1d< real64 > const & phaseDensity, + arraySlice1d< real64 > const & dPhaseDensity_dPressure, + arraySlice1d< real64 > const & dPhaseDensity_dTemperature, + arraySlice2d< real64 > const & dPhaseDensity_dGlobalCompFraction, + arraySlice1d< real64 > const & phaseMassDensity, + arraySlice1d< real64 > const & dPhaseMassDensity_dPressure, + arraySlice1d< real64 > const & dPhaseMassDensity_dTemperature, + arraySlice2d< real64 > const & dPhaseMassDensity_dGlobalCompFraction, + arraySlice1d< real64 > const & phaseViscosity, + arraySlice1d< real64 > const & dPhaseViscosity_dPressure, + arraySlice1d< real64 > const & dPhaseViscosity_dTemperature, + arraySlice2d< real64 > const & dPhaseViscosity_dGlobalCompFraction, + arraySlice2d< real64 > const & phaseCompFraction, + arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, + arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, + arraySlice3d< real64 > const & dPhaseCompFraction_dGlobalCompFraction, + real64 & totalDensity, + real64 & dTotalDensity_dPressure, + real64 & dTotalDensity_dTemperature, + arraySlice1d< real64 > const & dTotalDensity_dGlobalCompFraction ) const +{ + // 0. make shortcut structs to avoid long names (TODO maybe remove) + CompositionalVarContainer< 1 > phaseFrac { + phaseFraction, + dPhaseFraction_dPressure, + dPhaseFraction_dTemperature, + dPhaseFraction_dGlobalCompFraction + }; + + CompositionalVarContainer< 1 > phaseDens { + phaseDensity, + dPhaseDensity_dPressure, + dPhaseDensity_dTemperature, + dPhaseDensity_dGlobalCompFraction + }; + + CompositionalVarContainer< 1 > phaseMassDens { + phaseMassDensity, + dPhaseMassDensity_dPressure, + dPhaseMassDensity_dTemperature, + dPhaseMassDensity_dGlobalCompFraction + }; + + CompositionalVarContainer< 1 > phaseVisc { + phaseViscosity, + dPhaseViscosity_dPressure, + dPhaseViscosity_dTemperature, + dPhaseViscosity_dGlobalCompFraction + }; + + CompositionalVarContainer< 2 > phaseCompFrac { + phaseCompFraction, + dPhaseCompFraction_dPressure, + dPhaseCompFraction_dTemperature, + dPhaseCompFraction_dGlobalCompFraction + }; + + CompositionalVarContainer< 0 > totalDens { + totalDensity, + dTotalDensity_dPressure, + dTotalDensity_dTemperature, + dTotalDensity_dGlobalCompFraction + }; + +#if defined(__CUDACC__) + // For some reason nvcc thinks these aren't used. + GEOSX_UNUSED_VAR( phaseFrac, phaseDens, phaseMassDens, phaseVisc, phaseCompFrac, totalDens ); +#endif + + constexpr localIndex numComps = 2; + constexpr localIndex numPhases = 2; + localIndex const ipGas = m_phaseGasIndex; + localIndex const ipLiq = m_phaseLiquidIndex; + + // 1. Convert input mass fractions to mole fractions and keep derivatives + + stackArray1d< real64, numComps > compMoleFrac( numComps ); + stackArray2d< real64, numComps *numComps > dCompMoleFrac_dCompMassFrac( numComps, numComps ); + + if( m_useMass ) + { + real64 totalMolality = 0.0; + for( localIndex ic = 0; ic < numComps; ++ic ) + { + real64 const mwInv = 1.0 / m_componentMolarWeight[ic]; + compMoleFrac[ic] = composition[ic] * mwInv; // this is molality (units of mole/mass) + dCompMoleFrac_dCompMassFrac[ic][ic] = mwInv; + totalMolality += compMoleFrac[ic]; + } + + real64 const totalMolalityInv = 1.0 / totalMolality; + for( localIndex ic = 0; ic < numComps; ++ic ) + { + compMoleFrac[ic] *= totalMolalityInv; + + for( localIndex jc = 0; jc < numComps; ++jc ) + { + dCompMoleFrac_dCompMassFrac[ic][jc] -= compMoleFrac[ic] / m_componentMolarWeight[jc]; + dCompMoleFrac_dCompMassFrac[ic][jc] *= totalMolalityInv; + } + } + } + else + { + for( localIndex ic = 0; ic < numComps; ++ic ) + { + compMoleFrac[ic] = composition[ic]; + } + } + + // 2. Compute phase fractions and phase component fractions + + real64 const temperatureInCelsius = temperature - 273.15; + m_co2SolubilityWrapper[0].compute( pressure, + temperatureInCelsius, + compMoleFrac, + phaseFrac.value, phaseFrac.dPres, phaseFrac.dTemp, phaseFrac.dComp, + phaseCompFrac.value, phaseCompFrac.dPres, phaseCompFrac.dTemp, phaseCompFrac.dComp ); + + // 3. Compute phase densities and phase viscosities + + m_co2DensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ipGas], + phaseDens.value[ipGas], phaseDens.dPres[ipGas], phaseDens.dTemp[ipGas], phaseDens.dComp[ipGas], + m_useMass ); + m_co2ViscosityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ipGas], + phaseVisc.value[ipGas], phaseVisc.dPres[ipGas], phaseVisc.dTemp[ipGas], phaseVisc.dComp[ipGas], + m_useMass ); + + m_brineDensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ipLiq], + phaseDens.value[ipLiq], phaseDens.dPres[ipLiq], phaseDens.dTemp[ipLiq], phaseDens.dComp[ipLiq], + m_useMass ); + m_brineViscosityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ipLiq], + phaseVisc.value[ipLiq], phaseVisc.dPres[ipLiq], phaseVisc.dTemp[ipLiq], phaseVisc.dComp[ipLiq], + m_useMass ); + + // 4. Depending on the m_useMass flag, convert to mass variables or simply compute mass density + + // TODO: for now the treatment of molar/mass density requires too many interpolations in the tables, it needs to be fixed + // we should modify the PVT functions so that they can return phaseMassDens, phaseDens, and phaseMW in one call + // TODO: extract the following piece of code and write a function that can be used here and in MultiFluidPVTPackageWrapper + + if( m_useMass ) + { + // 4.1. Convert phase fractions (requires two passes) + real64 totalMass{}; + real64 dTotalMass_dP{}; + real64 dTotalMass_dT{}; + real64 dTotalMass_dC[2]{}; + + // 4.1.0. Compute the phase molecular weights (ultimately, get that from the PVT function) + real64 phaseMW[2]{}; + real64 dPhaseMW_dPres[2]{}; + real64 dPhaseMW_dTemp[2]{}; + real64 dPhaseMW_dComp[2][2]{}; + real64 phaseMolarDens = 0.0; + real64 dPhaseMolarDens_dPres = 0.0; + real64 dPhaseMolarDens_dTemp = 0.0; + stackArray1d< real64, numComps > dPhaseMolarDens_dComp( 2 ); + m_co2DensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ipGas], + phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, + 0 ); + phaseMW[ipGas] = phaseDens.value[ipGas] / phaseMolarDens; + dPhaseMW_dPres[ipGas] = phaseDens.dPres[ipGas] / phaseMolarDens - phaseMW[ipGas]*dPhaseMolarDens_dPres / phaseMolarDens; + dPhaseMW_dTemp[ipGas] = phaseDens.dTemp[ipGas] / phaseMolarDens - phaseMW[ipGas]*dPhaseMolarDens_dTemp / phaseMolarDens; + for( localIndex ic = 0; ic < numComps; ++ic ) + { + dPhaseMW_dComp[ipGas][ic] = phaseDens.dComp[ipGas][ic] / phaseMolarDens - phaseMW[ipGas]*dPhaseMolarDens_dComp[ic] / phaseMolarDens; + } + m_brineDensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ipLiq], + phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, + 0 ); + phaseMW[ipLiq] = phaseDens.value[ipLiq] / phaseMolarDens; + dPhaseMW_dPres[ipLiq] = phaseDens.dPres[ipLiq] / phaseMolarDens - phaseMW[ipLiq]*dPhaseMolarDens_dPres / phaseMolarDens; + dPhaseMW_dTemp[ipLiq] = phaseDens.dTemp[ipLiq] / phaseMolarDens - phaseMW[ipLiq]*dPhaseMolarDens_dTemp / phaseMolarDens; + for( localIndex ic = 0; ic < numComps; ++ic ) + { + dPhaseMW_dComp[ipLiq][ic] = phaseDens.dComp[ipLiq][ic] / phaseMolarDens - phaseMW[ipLiq]*dPhaseMolarDens_dComp[ic]/phaseMolarDens; + } + + + // 4.1.1. Compute mass of each phase and total mass (on a 1-mole basis) + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + real64 const nu = phaseFrac.value[ip]; + + phaseFrac.value[ip] *= phaseMW[ip]; + phaseFrac.dPres[ip] = phaseFrac.dPres[ip] * phaseMW[ip] + nu * dPhaseMW_dPres[ip]; + phaseFrac.dTemp[ip] = phaseFrac.dTemp[ip] * phaseMW[ip] + nu * dPhaseMW_dTemp[ip]; + + totalMass += phaseFrac.value[ip]; + dTotalMass_dP += phaseFrac.dPres[ip]; + dTotalMass_dT += phaseFrac.dTemp[ip]; + + for( localIndex jc = 0; jc < numComps; ++jc ) + { + phaseFrac.dComp[ip][jc] = phaseFrac.dComp[ip][jc] * phaseMW[ip] + nu * dPhaseMW_dComp[ip][jc]; + dTotalMass_dC[jc] += phaseFrac.dComp[ip][jc]; + } + } + + // 4.1.2. Normalize to get mass fractions + real64 const totalMassInv = 1.0 / totalMass; + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + phaseFrac.value[ip] *= totalMassInv; + phaseFrac.dPres[ip] = ( phaseFrac.dPres[ip] - phaseFrac.value[ip] * dTotalMass_dP ) * totalMassInv; + phaseFrac.dTemp[ip] = ( phaseFrac.dTemp[ip] - phaseFrac.value[ip] * dTotalMass_dT ) * totalMassInv; + + for( localIndex jc = 0; jc < numComps; ++jc ) + { + phaseFrac.dComp[ip][jc] = ( phaseFrac.dComp[ip][jc] - phaseFrac.value[ip] * dTotalMass_dC[jc] ) * totalMassInv; + } + } + + // 4.2. Convert phase compositions + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + real64 const phaseMWInv = 1.0 / phaseMW[ip]; + + for( localIndex ic = 0; ic < numComps; ++ic ) + { + + real64 const compMW = m_componentMolarWeight[ic]; + + phaseCompFrac.value[ip][ic] = phaseCompFrac.value[ip][ic] * compMW * phaseMWInv; + phaseCompFrac.dPres[ip][ic] = + ( phaseCompFrac.dPres[ip][ic] * compMW - phaseCompFrac.value[ip][ic] * dPhaseMW_dPres[ip] ) * phaseMWInv; + phaseCompFrac.dTemp[ip][ic] = + ( phaseCompFrac.dTemp[ip][ic] * compMW - phaseCompFrac.value[ip][ic] * dPhaseMW_dTemp[ip] ) * phaseMWInv; + + for( localIndex jc = 0; jc < numComps; ++jc ) + { + phaseCompFrac.dComp[ip][ic][jc] = + ( phaseCompFrac.dComp[ip][ic][jc] * compMW - phaseCompFrac.value[ip][ic] * dPhaseMW_dComp[ip][jc] ) * phaseMWInv; + } + } + } + + // 4.3. Update derivatives w.r.t. mole fractions to derivatives w.r.t mass fractions + real64 work[numComps]{}; + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + applyChainRuleInPlace( numComps, dCompMoleFrac_dCompMassFrac, phaseFrac.dComp[ip], work ); + applyChainRuleInPlace( numComps, dCompMoleFrac_dCompMassFrac, phaseDens.dComp[ip], work ); + + for( localIndex ic = 0; ic < numComps; ++ic ) + { + applyChainRuleInPlace( numComps, dCompMoleFrac_dCompMassFrac, phaseCompFrac.dComp[ip][ic], work ); + } + } + + // 4.4 Copy the phase densities into the phase mass densities + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + phaseMassDens.value[ip] = phaseDens.value[ip]; + phaseMassDens.dPres[ip] = phaseDens.dPres[ip]; + phaseMassDens.dTemp[ip] = phaseDens.dTemp[ip]; + for( localIndex ic = 0; ic < numComps; ++ic ) + { + phaseMassDens.dComp[ip][ic] = phaseDens.dComp[ip][ic]; + } + } + } + else + { + // for now, we have to compute the phase mass density here + m_co2DensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ipGas], + phaseMassDens.value[ipGas], phaseMassDens.dPres[ipGas], + phaseMassDens.dTemp[ipGas], phaseMassDens.dComp[ipGas], + true ); + m_brineDensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ipLiq], + phaseMassDens.value[ipLiq], phaseMassDens.dPres[ipLiq], + phaseMassDens.dTemp[ipLiq], phaseMassDens.dComp[ipLiq], + true ); + } + + // TODO: extract the following piece of code and write a function that can be used here and in MultiFluidPVTPackageWrapper + + // 5. Compute total fluid mass/molar density and derivatives + { + totalDens.value = 0.0; + totalDens.dPres = 0.0; + totalDens.dTemp = 0.0; + for( localIndex jc = 0; jc < numComps; ++jc ) + { + totalDens.dComp[jc] = 0.0; + } + + // 5.1. Sum mass/molar fraction/density ratio over all phases to get the inverse of density + for( localIndex ip = 0; ip < numPhases; ++ip ) + { + real64 const densInv = 1.0 / phaseDens.value[ip]; + real64 const value = phaseFrac.value[ip] * densInv; + + totalDens.value += value; + totalDens.dPres += ( phaseFrac.dPres[ip] - value * phaseDens.dPres[ip] ) * densInv; + totalDens.dTemp += ( phaseFrac.dTemp[ip] - value * phaseDens.dTemp[ip] ) * densInv; + + for( localIndex jc = 0; jc < numComps; ++jc ) + { + totalDens.dComp[jc] += ( phaseFrac.dComp[ip][jc] - value * phaseDens.dComp[ip][jc] ) * densInv; + } + } + + // 5.2. Invert the previous quantity to get actual density + totalDens.value = 1.0 / totalDens.value; + real64 const minusDens2 = -totalDens.value * totalDens.value; + totalDens.dPres *= minusDens2; + totalDens.dTemp *= minusDens2; + + for( localIndex jc = 0; jc < numComps; ++jc ) + { + totalDens.dComp[jc] *= minusDens2; + } + } +} + } //namespace constitutive } //namespace geosx diff --git a/src/coreComponents/constitutive/fluid/NewMultiPhaseMultiComponentFluid.cpp b/src/coreComponents/constitutive/fluid/NewMultiPhaseMultiComponentFluid.cpp deleted file mode 100644 index 8a839b155b5..00000000000 --- a/src/coreComponents/constitutive/fluid/NewMultiPhaseMultiComponentFluid.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * 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 Total, S.A - * Copyright (c) 2019- GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file NewMultiPhaseMultiComponentFluid.cpp - */ -#include "NewMultiPhaseMultiComponentFluid.hpp" - -#include "common/Path.hpp" -#include "managers/ProblemManager.hpp" - -namespace geosx -{ - -using namespace dataRepository; -using namespace PVTProps; -using namespace stringutilities; - -namespace constitutive -{ - -NewMultiPhaseMultiComponentFluid::NewMultiPhaseMultiComponentFluid( string const & name, Group * const parent ): - MultiFluidBase( name, parent ) -{ - registerWrapper( viewKeyStruct::phasePVTParaFilesString(), &m_phasePVTParaFiles ). - setInputFlag( InputFlags::REQUIRED ). - setRestartFlags( RestartFlags::NO_WRITE ). - setDescription( "Names of the files defining the parameters of the viscosity and density models" ); - - registerWrapper( viewKeyStruct::flashModelParaFileString(), &m_flashModelParaFile ). - setInputFlag( InputFlags::REQUIRED ). - setRestartFlags( RestartFlags::NO_WRITE ). - setDescription( "Name of the file defining the parameters of the flash model" ); -} - -NewMultiPhaseMultiComponentFluid::~NewMultiPhaseMultiComponentFluid() -{} - - -std::unique_ptr< ConstitutiveBase > -NewMultiPhaseMultiComponentFluid::deliverClone( string const & name, - Group * const parent ) const -{ - std::unique_ptr< ConstitutiveBase > clone = MultiFluidBase::deliverClone( name, parent ); - - NewMultiPhaseMultiComponentFluid * const newConstitutiveRelation = dynamic_cast< NewMultiPhaseMultiComponentFluid * >(clone.get()); - newConstitutiveRelation->m_phaseGasIndex = this->m_phaseGasIndex; - newConstitutiveRelation->m_phaseLiquidIndex = this->m_phaseLiquidIndex; - - newConstitutiveRelation->createPVTModels(); - - return clone; -} - -void NewMultiPhaseMultiComponentFluid::postProcessInput() -{ - MultiFluidBase::postProcessInput(); - - localIndex const numPhases = numFluidPhases(); - localIndex const numComps = numFluidComponents(); - GEOSX_ERROR_IF( numPhases != 2, "The number of phases in this model should be equal to 2" ); - GEOSX_ERROR_IF( numComps != 2, "The number of components in this model should be equal to 2" ); - GEOSX_ERROR_IF( m_phasePVTParaFiles.size() != 2, "The number of phasePVTParaFiles is not the same as the number of phases!" ); - - bool notFound = true; - for( localIndex i = 0; i < m_phaseNames.size(); ++i ) - { - if( m_phaseNames[i] == "CO2" || m_phaseNames[i] == "co2" || - m_phaseNames[i] == "gas" || m_phaseNames[i] == "Gas" ) - { - m_phaseGasIndex = i; - notFound = false; - break; - } - } - GEOSX_ERROR_IF( notFound, "Phase co2/gas is not found!" ); - - notFound = true; - for( localIndex i = 0; i < m_phaseNames.size(); ++i ) - { - if( m_phaseNames[i] == "Water" || m_phaseNames[i] == "water" || - m_phaseNames[i] == "Liquid" || m_phaseNames[i] == "liquid" ) - { - m_phaseLiquidIndex = i; - notFound = false; - break; - } - } - GEOSX_ERROR_IF( notFound, "Phase water/liquid is not found!" ); - - createPVTModels(); -} - -void NewMultiPhaseMultiComponentFluid::createPVTModels() -{ - // 1) Create the viscosity and density models - for( string const & filename : m_phasePVTParaFiles ) - { - std::ifstream is( filename ); - constexpr std::streamsize buf_size = 256; - char buf[buf_size]; - - while( is.getline( buf, buf_size ) ) - { - string const str( buf ); - string_array const strs = Tokenize( str, " " ); - if( strs[0] == "DensityFun" ) - { - if( strs[1] == "SpanWagnerCO2Density" ) - { - m_co2Density = std::make_unique< SpanWagnerCO2Density >( strs, m_componentNames, m_componentMolarWeight ); - m_co2DensityWrapper.emplace_back( m_co2Density->createKernelWrapper() ); - } - else if( strs[1] == "BrineCO2Density" ) - { - m_brineDensity = std::make_unique< BrineCO2Density >( strs, m_componentNames, m_componentMolarWeight ); - m_brineDensityWrapper.emplace_back( m_brineDensity->createKernelWrapper() ); - } - } - else if( strs[0] == "ViscosityFun" ) - { - if( strs[1] == "FenghourCO2Viscosity" ) - { - m_co2Viscosity = std::make_unique< FenghourCO2Viscosity >( strs, m_componentNames, m_componentMolarWeight ); - m_co2ViscosityWrapper.emplace_back( m_co2Viscosity->createKernelWrapper() ); - } - else if( strs[1] == "BrineViscosity" ) - { - m_brineViscosity = std::make_unique< BrineViscosity >( strs, m_componentNames, m_componentMolarWeight ); - m_brineViscosityWrapper.emplace_back( m_brineViscosity->createKernelWrapper() ); - } - } - else - { - GEOSX_ERROR( "Error: Invalid PVT function: " << strs[0] << "." ); - } - } - is.close(); - } - - GEOSX_ERROR_IF( m_co2Density == nullptr, "SpanWagnerCO2Density model not found" ); - GEOSX_ERROR_IF( m_brineDensity == nullptr, "BrineCO2Density model not found" ); - GEOSX_ERROR_IF( m_co2Viscosity == nullptr, "FenghourCO2Viscosity model not found" ); - GEOSX_ERROR_IF( m_brineViscosity == nullptr, "BrineViscosity model not found" ); - - // 2) Create the flash model - { - std::ifstream is( m_flashModelParaFile ); - constexpr std::streamsize buf_size = 256; - char buf[buf_size]; - - while( is.getline( buf, buf_size ) ) - { - string const str( buf ); - string_array const strs = Tokenize( str, " " ); - if( strs[0] == "FlashModel" && strs[1] == "CO2Solubility" ) - { - m_co2Solubility = std::make_unique< CO2Solubility >( strs, m_phaseNames, m_componentNames, m_componentMolarWeight ); - m_co2SolubilityWrapper.emplace_back( m_co2Solubility->createKernelWrapper() ); - } - else - { - GEOSX_ERROR( "Error: Invalid flash model: " << strs[0] << ", " << strs[1] << "." ); - } - } - is.close(); - } - - GEOSX_ERROR_IF( m_co2Solubility == nullptr, "CO2Solubility model not found" ); -} - -REGISTER_CATALOG_ENTRY( ConstitutiveBase, NewMultiPhaseMultiComponentFluid, string const &, Group * const ) - -} //namespace constitutive - -} //namespace geosx diff --git a/src/coreComponents/constitutive/fluid/NewMultiPhaseMultiComponentFluid.hpp b/src/coreComponents/constitutive/fluid/NewMultiPhaseMultiComponentFluid.hpp deleted file mode 100644 index 7eaf30fb6ea..00000000000 --- a/src/coreComponents/constitutive/fluid/NewMultiPhaseMultiComponentFluid.hpp +++ /dev/null @@ -1,885 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * 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 Total, S.A - * Copyright (c) 2019- GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file NewMultiPhaseMultiComponentFluid.hpp - */ - -#ifndef GEOSX_CONSTITUTIVE_FLUID_NEWMULTIPHASEMULTICOMPONENTFLUID_HPP_ -#define GEOSX_CONSTITUTIVE_FLUID_NEWMULTIPHASEMULTICOMPONENTFLUID_HPP_ - -#include "constitutive/fluid/MultiFluidBase.hpp" -#include "constitutive/fluid/MultiFluidUtils.hpp" -#include "PVTFunctions/NewBrineCO2DensityFunction.hpp" -#include "PVTFunctions/NewSpanWagnerCO2DensityFunction.hpp" -#include "PVTFunctions/NewBrineViscosityFunction.hpp" -#include "PVTFunctions/NewFenghourCO2ViscosityFunction.hpp" -#include "PVTFunctions/NewCO2SolubilityFunction.hpp" - -#include - -namespace geosx -{ - -namespace constitutive -{ - -/** - * @brief Kernel wrapper class for NewMultiPhaseMultiComponentFluid. - */ -class NewMultiPhaseMultiComponentFluidUpdate final : public MultiFluidBaseUpdate -{ -public: - - NewMultiPhaseMultiComponentFluidUpdate( localIndex const phaseGasIndex, - localIndex const phaseLiquidIndex, - arrayView1d< PVTProps::BrineViscosity::KernelWrapper const > const & brineViscosityWrapper, - arrayView1d< PVTProps::FenghourCO2Viscosity::KernelWrapper const > const & co2ViscosityWrapper, - arrayView1d< PVTProps::BrineCO2Density::KernelWrapper const > const & brineDensityWrapper, - arrayView1d< PVTProps::SpanWagnerCO2Density::KernelWrapper const > const & co2DensityWrapper, - arrayView1d< PVTProps::CO2Solubility::KernelWrapper const > const & co2SolubilityWrapper, - arrayView1d< real64 const > const & componentMolarWeight, - bool useMass, - arrayView3d< real64 > const & phaseFraction, - arrayView3d< real64 > const & dPhaseFraction_dPressure, - arrayView3d< real64 > const & dPhaseFraction_dTemperature, - arrayView4d< real64 > const & dPhaseFraction_dGlobalCompFraction, - arrayView3d< real64 > const & phaseDensity, - arrayView3d< real64 > const & dPhaseDensity_dPressure, - arrayView3d< real64 > const & dPhaseDensity_dTemperature, - arrayView4d< real64 > const & dPhaseDensity_dGlobalCompFraction, - arrayView3d< real64 > const & phaseMassDensity, - arrayView3d< real64 > const & dPhaseMassDensity_dPressure, - arrayView3d< real64 > const & dPhaseMassDensity_dTemperature, - arrayView4d< real64 > const & dPhaseMassDensity_dGlobalCompFraction, - arrayView3d< real64 > const & phaseViscosity, - arrayView3d< real64 > const & dPhaseViscosity_dPressure, - arrayView3d< real64 > const & dPhaseViscosity_dTemperature, - arrayView4d< real64 > const & dPhaseViscosity_dGlobalCompFraction, - arrayView4d< real64 > const & phaseCompFraction, - arrayView4d< real64 > const & dPhaseCompFraction_dPressure, - arrayView4d< real64 > const & dPhaseCompFraction_dTemperature, - arrayView5d< real64 > const & dPhaseCompFraction_dGlobalCompFraction, - arrayView2d< real64 > const & totalDensity, - arrayView2d< real64 > const & dTotalDensity_dPressure, - arrayView2d< real64 > const & dTotalDensity_dTemperature, - arrayView3d< real64 > const & dTotalDensity_dGlobalCompFraction ) - : MultiFluidBaseUpdate( componentMolarWeight, - useMass, - phaseFraction, - dPhaseFraction_dPressure, - dPhaseFraction_dTemperature, - dPhaseFraction_dGlobalCompFraction, - phaseDensity, - dPhaseDensity_dPressure, - dPhaseDensity_dTemperature, - dPhaseDensity_dGlobalCompFraction, - phaseMassDensity, - dPhaseMassDensity_dPressure, - dPhaseMassDensity_dTemperature, - dPhaseMassDensity_dGlobalCompFraction, - phaseViscosity, - dPhaseViscosity_dPressure, - dPhaseViscosity_dTemperature, - dPhaseViscosity_dGlobalCompFraction, - phaseCompFraction, - dPhaseCompFraction_dPressure, - dPhaseCompFraction_dTemperature, - dPhaseCompFraction_dGlobalCompFraction, - totalDensity, - dTotalDensity_dPressure, - dTotalDensity_dTemperature, - dTotalDensity_dGlobalCompFraction ), - m_phaseGasIndex( phaseGasIndex ), - m_phaseLiquidIndex( phaseLiquidIndex ), - m_brineViscosityWrapper( brineViscosityWrapper ), - m_co2ViscosityWrapper( co2ViscosityWrapper ), - m_brineDensityWrapper( brineDensityWrapper ), - m_co2DensityWrapper( co2DensityWrapper ), - m_co2SolubilityWrapper( co2SolubilityWrapper ) - {} - - /// Default copy constructor - NewMultiPhaseMultiComponentFluidUpdate( NewMultiPhaseMultiComponentFluidUpdate const & ) = default; - - /// Default move constructor - NewMultiPhaseMultiComponentFluidUpdate( NewMultiPhaseMultiComponentFluidUpdate && ) = default; - - /// Deleted copy assignment operator - NewMultiPhaseMultiComponentFluidUpdate & operator=( NewMultiPhaseMultiComponentFluidUpdate const & ) = delete; - - /// Deleted move assignment operator - NewMultiPhaseMultiComponentFluidUpdate & operator=( NewMultiPhaseMultiComponentFluidUpdate && ) = delete; - - //GEOSX_HOST_DEVICE - GEOSX_FORCE_INLINE - virtual void compute( real64 const pressure, - real64 const temperature, - arraySlice1d< real64 const > const & composition, - arraySlice1d< real64 > const & phaseFraction, - arraySlice1d< real64 > const & phaseDensity, - arraySlice1d< real64 > const & phaseMassDensity, - arraySlice1d< real64 > const & phaseViscosity, - arraySlice2d< real64 > const & phaseCompFraction, - real64 & totalDensity ) const override; - - //GEOSX_HOST_DEVICE - GEOSX_FORCE_INLINE - virtual void compute( real64 const pressure, - real64 const temperature, - arraySlice1d< real64 const > const & composition, - arraySlice1d< real64 > const & phaseFraction, - arraySlice1d< real64 > const & dPhaseFraction_dPressure, - arraySlice1d< real64 > const & dPhaseFraction_dTemperature, - arraySlice2d< real64 > const & dPhaseFraction_dGlobalCompFraction, - arraySlice1d< real64 > const & phaseDensity, - arraySlice1d< real64 > const & dPhaseDensity_dPressure, - arraySlice1d< real64 > const & dPhaseDensity_dTemperature, - arraySlice2d< real64 > const & dPhaseDensity_dGlobalCompFraction, - arraySlice1d< real64 > const & phaseMassDensity, - arraySlice1d< real64 > const & dPhaseMassDensity_dPressure, - arraySlice1d< real64 > const & dPhaseMassDensity_dTemperature, - arraySlice2d< real64 > const & dPhaseMassDensity_dGlobalCompFraction, - arraySlice1d< real64 > const & phaseViscosity, - arraySlice1d< real64 > const & dPhaseViscosity_dPressure, - arraySlice1d< real64 > const & dPhaseViscosity_dTemperature, - arraySlice2d< real64 > const & dPhaseViscosity_dGlobalCompFraction, - arraySlice2d< real64 > const & phaseCompFraction, - arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, - arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, - arraySlice3d< real64 > const & dPhaseCompFraction_dGlobalCompFraction, - real64 & totalDensity, - real64 & dTotalDensity_dPressure, - real64 & dTotalDensity_dTemperature, - arraySlice1d< real64 > const & dTotalDensity_dGlobalCompFraction ) const override; - - //GEOSX_HOST_DEVICE - GEOSX_FORCE_INLINE - virtual void update( localIndex const k, - localIndex const q, - real64 const pressure, - real64 const temperature, - arraySlice1d< real64 const > const & composition ) const override - { - compute( pressure, - temperature, - composition, - m_phaseFraction[k][q], - m_dPhaseFraction_dPressure[k][q], - m_dPhaseFraction_dTemperature[k][q], - m_dPhaseFraction_dGlobalCompFraction[k][q], - m_phaseDensity[k][q], - m_dPhaseDensity_dPressure[k][q], - m_dPhaseDensity_dTemperature[k][q], - m_dPhaseDensity_dGlobalCompFraction[k][q], - m_phaseMassDensity[k][q], - m_dPhaseMassDensity_dPressure[k][q], - m_dPhaseMassDensity_dTemperature[k][q], - m_dPhaseMassDensity_dGlobalCompFraction[k][q], - m_phaseViscosity[k][q], - m_dPhaseViscosity_dPressure[k][q], - m_dPhaseViscosity_dTemperature[k][q], - m_dPhaseViscosity_dGlobalCompFraction[k][q], - m_phaseCompFraction[k][q], - m_dPhaseCompFraction_dPressure[k][q], - m_dPhaseCompFraction_dTemperature[k][q], - m_dPhaseCompFraction_dGlobalCompFraction[k][q], - m_totalDensity[k][q], - m_dTotalDensity_dPressure[k][q], - m_dTotalDensity_dTemperature[k][q], - m_dTotalDensity_dGlobalCompFraction[k][q] ); - } - -private: - - /// Index of the gas phase - localIndex const m_phaseGasIndex; - - /// Index of the liquid phase - localIndex const m_phaseLiquidIndex; - - /// Kernel wrapper for brine viscosity updates - arrayView1d< PVTProps::BrineViscosity::KernelWrapper const > const m_brineViscosityWrapper; - - /// Kernel wrapper for CO2 viscosity updates - arrayView1d< PVTProps::FenghourCO2Viscosity::KernelWrapper const > const m_co2ViscosityWrapper; - - /// Kernel wrapper for brine density updates - arrayView1d< PVTProps::BrineCO2Density::KernelWrapper const > const m_brineDensityWrapper; - - /// Kernel wrapper for CO2 density updates - arrayView1d< PVTProps::SpanWagnerCO2Density::KernelWrapper const > const m_co2DensityWrapper; - - /// Kernel wrapper for phase fraction and phase component fraction updates - arrayView1d< PVTProps::CO2Solubility::KernelWrapper const > const m_co2SolubilityWrapper; -}; - -class NewMultiPhaseMultiComponentFluid : public MultiFluidBase -{ -public: - - NewMultiPhaseMultiComponentFluid( string const & name, Group * const parent ); - - virtual ~NewMultiPhaseMultiComponentFluid() override; - - virtual std::unique_ptr< ConstitutiveBase > - deliverClone( string const & name, - Group * const parent ) const override; - - - static string catalogName() { return "NewMultiPhaseMultiComponentFluid"; } - - virtual string getCatalogName() const override { return catalogName(); } - - /// Type of kernel wrapper for in-kernel update - using KernelWrapper = NewMultiPhaseMultiComponentFluidUpdate; - - /** - * @brief Create an update kernel wrapper. - * @return the wrapper - */ - KernelWrapper createKernelWrapper() - { - return KernelWrapper( m_phaseGasIndex, - m_phaseLiquidIndex, - m_brineViscosityWrapper.toViewConst(), - m_co2ViscosityWrapper.toViewConst(), - m_brineDensityWrapper.toViewConst(), - m_co2DensityWrapper.toViewConst(), - m_co2SolubilityWrapper.toViewConst(), - m_componentMolarWeight.toViewConst(), - m_useMass, - m_phaseFraction, - m_dPhaseFraction_dPressure, - m_dPhaseFraction_dTemperature, - m_dPhaseFraction_dGlobalCompFraction, - m_phaseDensity, - m_dPhaseDensity_dPressure, - m_dPhaseDensity_dTemperature, - m_dPhaseDensity_dGlobalCompFraction, - m_phaseMassDensity, - m_dPhaseMassDensity_dPressure, - m_dPhaseMassDensity_dTemperature, - m_dPhaseMassDensity_dGlobalCompFraction, - m_phaseViscosity, - m_dPhaseViscosity_dPressure, - m_dPhaseViscosity_dTemperature, - m_dPhaseViscosity_dGlobalCompFraction, - m_phaseCompFraction, - m_dPhaseCompFraction_dPressure, - m_dPhaseCompFraction_dTemperature, - m_dPhaseCompFraction_dGlobalCompFraction, - m_totalDensity, - m_dTotalDensity_dPressure, - m_dTotalDensity_dTemperature, - m_dTotalDensity_dGlobalCompFraction ); - } - - struct viewKeyStruct : MultiFluidBase::viewKeyStruct - { - static constexpr char const * flashModelParaFileString() { return "flashModelParaFile"; } - static constexpr char const * phasePVTParaFilesString() { return "phasePVTParaFiles"; } - } viewKeysNewMultiPhaseMultiComponentFluid; - - -protected: - - virtual void postProcessInput() override; - -private: - - void createPVTModels(); - - /// Names of the files defining the viscosity and density models - path_array m_phasePVTParaFiles; - - /// Name of the file defining the flash model - Path m_flashModelParaFile; - - /// Index of the gas phase - localIndex m_phaseGasIndex; - - /// Index of the liquid phase - localIndex m_phaseLiquidIndex; - - // TODO: Here I hard-coded all the types to avoid the virtual calls in the compute function. - // See if there is a way to reintroduce them. If it is not possible, the class should be - // renamed because it is not "multi-phase, multi-component", but just CO2-brine. - - /// Pointer to the brine viscosity model - std::unique_ptr< PVTProps::BrineViscosity > m_brineViscosity; - - /// Pointer to the CO2 viscosity model - std::unique_ptr< PVTProps::FenghourCO2Viscosity > m_co2Viscosity; - - /// Pointer to the brine density model - std::unique_ptr< PVTProps::BrineCO2Density > m_brineDensity; - - /// Pointer to the CO2 density model - std::unique_ptr< PVTProps::SpanWagnerCO2Density > m_co2Density; - - /// Pointer to the flash model - std::unique_ptr< PVTProps::CO2Solubility > m_co2Solubility; - - /// Pointer to the brine viscosity model - array1d< PVTProps::BrineViscosity::KernelWrapper > m_brineViscosityWrapper; - - /// Pointer to the CO2 viscosity model - array1d< PVTProps::FenghourCO2Viscosity::KernelWrapper > m_co2ViscosityWrapper; - - /// Pointer to the brine density model - array1d< PVTProps::BrineCO2Density::KernelWrapper > m_brineDensityWrapper; - - /// Pointer to the CO2 density model - array1d< PVTProps::SpanWagnerCO2Density::KernelWrapper > m_co2DensityWrapper; - - /// Pointer to the flash model - array1d< PVTProps::CO2Solubility::KernelWrapper > m_co2SolubilityWrapper; - -}; - -//GEOSX_HOST_DEVICE -GEOSX_FORCE_INLINE -void NewMultiPhaseMultiComponentFluidUpdate::compute( real64 pressure, - real64 temperature, - arraySlice1d< real64 const > const & composition, - arraySlice1d< real64 > const & phaseFraction, - arraySlice1d< real64 > const & phaseDensity, - arraySlice1d< real64 > const & phaseMassDensity, - arraySlice1d< real64 > const & phaseViscosity, - arraySlice2d< real64 > const & phaseCompFraction, - real64 & totalDensity ) const -{ - constexpr localIndex numComps = 2; - constexpr localIndex numPhases = 2; - localIndex const ipGas = m_phaseGasIndex; - localIndex const ipLiq = m_phaseLiquidIndex; - - // for now, compute the derivatives and discard them - stackArray1d< real64, numPhases > dPhaseFrac_dPres( numPhases ); - stackArray1d< real64, numPhases > dPhaseFrac_dTemp( numPhases ); - stackArray2d< real64, numPhases *numComps > dPhaseFrac_dComp( numPhases, numComps ); - stackArray2d< real64, numPhases *numComps > dPhaseCompFrac_dPres( numPhases, numComps ); - stackArray2d< real64, numPhases *numComps > dPhaseCompFrac_dTemp( numPhases, numComps ); - stackArray3d< real64, numPhases *numComps *numComps > dPhaseCompFrac_dComp( numPhases, numComps, numComps ); - real64 dPhaseDens_dPres = 0.0; - real64 dPhaseDens_dTemp = 0.0; - stackArray1d< real64, numComps > dPhaseDens_dComp( numComps ); - real64 dPhaseMassDens_dPres = 0.0; - real64 dPhaseMassDens_dTemp = 0.0; - stackArray1d< real64, numComps > dPhaseMassDens_dComp( numComps ); - real64 dPhaseVisc_dPres = 0.0; - real64 dPhaseVisc_dTemp = 0.0; - stackArray1d< real64, numComps > dPhaseVisc_dComp( numComps ); - - // 1. Convert input mass fractions to mole fractions and keep derivatives - - stackArray1d< real64, numComps > compMoleFrac( numComps ); - if( m_useMass ) - { - real64 totalMolality = 0.0; - for( localIndex ic = 0; ic < numComps; ++ic ) - { - real64 const mwInv = 1.0 / m_componentMolarWeight[ic]; - compMoleFrac[ic] = composition[ic] * mwInv; // this is molality (units of mole/mass) - totalMolality += compMoleFrac[ic]; - } - - real64 const totalMolalityInv = 1.0 / totalMolality; - for( localIndex ic = 0; ic < numComps; ++ic ) - { - compMoleFrac[ic] *= totalMolalityInv; - } - } - else - { - for( localIndex ic = 0; ic < numComps; ++ic ) - { - compMoleFrac[ic] = composition[ic]; - } - } - - // 2. Compute phase fractions and phase component fractions - - real64 const temperatureInCelsius = temperature - 273.15; - m_co2SolubilityWrapper[0].compute( pressure, - temperatureInCelsius, - compMoleFrac, - phaseFraction, dPhaseFrac_dPres, dPhaseFrac_dTemp, dPhaseFrac_dComp, - phaseCompFraction, dPhaseCompFrac_dPres, dPhaseCompFrac_dTemp, dPhaseCompFrac_dComp ); - - // 3. Compute phase densities and phase viscosities - - m_co2DensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFraction[ipGas], - phaseDensity[ipGas], dPhaseDens_dPres, dPhaseDens_dTemp, dPhaseDens_dComp, - m_useMass ); - m_co2ViscosityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFraction[ipGas], - phaseViscosity[ipGas], dPhaseVisc_dPres, dPhaseVisc_dTemp, dPhaseVisc_dComp, - m_useMass ); - - m_brineDensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFraction[ipLiq], - phaseDensity[ipLiq], dPhaseDens_dPres, dPhaseDens_dTemp, dPhaseDens_dComp, - m_useMass ); - m_brineViscosityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFraction[ipLiq], - phaseViscosity[ipLiq], dPhaseVisc_dPres, dPhaseVisc_dTemp, dPhaseVisc_dComp, - m_useMass ); - - // 4. Depending on the m_useMass flag, convert to mass variables or simply compute mass density - - // TODO: for now the treatment of molar/mass density requires too many interpolations in the tables, it needs to be fixed - // we should modify the PVT functions so that they can return phaseMassDens, phaseDens, and phaseMW in one call - // TODO: extract the following piece of code and write a function that can be used here and in MultiFluidPVTPackageWrapper - - if( m_useMass ) - { - // 4.1. Convert phase fractions (requires two passes) - real64 totalMass{}; - - // 4.1.0. Compute the phase molecular weights (ultimately, get that from the PVT function) - real64 phaseMW[2]{}; - real64 phaseMolarDens = 0.0; - real64 dPhaseMolarDens_dPres = 0.0; - real64 dPhaseMolarDens_dTemp = 0.0; - stackArray1d< real64, numComps > dPhaseMolarDens_dComp( 2 ); - m_co2DensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFraction[ipGas], - phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, - 0 ); - phaseMW[ipGas] = phaseDensity[ipGas] / phaseMolarDens; - m_brineDensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFraction[ipLiq], - phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, - 0 ); - phaseMW[ipLiq] = phaseDensity[ipLiq] / phaseMolarDens; - - // 4.1.1. Compute mass of each phase and total mass (on a 1-mole basis) - for( localIndex ip = 0; ip < numPhases; ++ip ) - { - phaseFraction[ip] *= phaseMW[ip]; - totalMass += phaseFraction[ip]; - } - // 4.1.2. Normalize to get mass fractions - real64 const totalMassInv = 1.0 / totalMass; - for( localIndex ip = 0; ip < numPhases; ++ip ) - { - phaseFraction[ip] *= totalMassInv; - } - // 4.2. Convert phase compositions - for( localIndex ip = 0; ip < numPhases; ++ip ) - { - real64 const phaseMWInv = 1.0 / phaseMW[ip]; - - for( localIndex ic = 0; ic < numComps; ++ic ) - { - real64 const compMW = m_componentMolarWeight[ic]; - phaseCompFraction[ip][ic] = phaseCompFraction[ip][ic] * compMW * phaseMWInv; - } - } - // 4.3 Copy the phase densities into the phase mass densities - for( localIndex ip = 0; ip < numPhases; ++ip ) - { - phaseMassDensity[ip] = phaseDensity[ip]; - } - } - else - { - // for now, we have to compute the phase mass density here - m_co2DensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFraction[ipGas], - phaseMassDensity[ipGas], dPhaseMassDens_dPres, - dPhaseMassDens_dTemp, dPhaseMassDens_dComp, - true ); - m_brineDensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFraction[ipLiq], - phaseMassDensity[ipLiq], dPhaseMassDens_dPres, - dPhaseMassDens_dTemp, dPhaseMassDens_dComp, - true ); - } - - // TODO: extract the following piece of code and write a function that can be used here and in MultiFluidPVTPackageWrapper - - // 5. Compute total fluid mass/molar density and derivatives - { - totalDensity = 0.0; - // 5.1. Sum mass/molar fraction/density ratio over all phases to get the inverse of density - for( localIndex ip = 0; ip < numPhases; ++ip ) - { - real64 const densInv = 1.0 / phaseDensity[ip]; - real64 const value = phaseFraction[ip] * densInv; - totalDensity += value; - } - // 5.2. Invert the previous quantity to get actual density - totalDensity = 1.0 / totalDensity; - } -} - -//GEOSX_HOST_DEVICE -GEOSX_FORCE_INLINE -void NewMultiPhaseMultiComponentFluidUpdate::compute( real64 pressure, - real64 temperature, - arraySlice1d< real64 const > const & composition, - arraySlice1d< real64 > const & phaseFraction, - arraySlice1d< real64 > const & dPhaseFraction_dPressure, - arraySlice1d< real64 > const & dPhaseFraction_dTemperature, - arraySlice2d< real64 > const & dPhaseFraction_dGlobalCompFraction, - arraySlice1d< real64 > const & phaseDensity, - arraySlice1d< real64 > const & dPhaseDensity_dPressure, - arraySlice1d< real64 > const & dPhaseDensity_dTemperature, - arraySlice2d< real64 > const & dPhaseDensity_dGlobalCompFraction, - arraySlice1d< real64 > const & phaseMassDensity, - arraySlice1d< real64 > const & dPhaseMassDensity_dPressure, - arraySlice1d< real64 > const & dPhaseMassDensity_dTemperature, - arraySlice2d< real64 > const & dPhaseMassDensity_dGlobalCompFraction, - arraySlice1d< real64 > const & phaseViscosity, - arraySlice1d< real64 > const & dPhaseViscosity_dPressure, - arraySlice1d< real64 > const & dPhaseViscosity_dTemperature, - arraySlice2d< real64 > const & dPhaseViscosity_dGlobalCompFraction, - arraySlice2d< real64 > const & phaseCompFraction, - arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, - arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, - arraySlice3d< real64 > const & dPhaseCompFraction_dGlobalCompFraction, - real64 & totalDensity, - real64 & dTotalDensity_dPressure, - real64 & dTotalDensity_dTemperature, - arraySlice1d< real64 > const & dTotalDensity_dGlobalCompFraction ) const -{ - // 0. make shortcut structs to avoid long names (TODO maybe remove) - CompositionalVarContainer< 1 > phaseFrac { - phaseFraction, - dPhaseFraction_dPressure, - dPhaseFraction_dTemperature, - dPhaseFraction_dGlobalCompFraction - }; - - CompositionalVarContainer< 1 > phaseDens { - phaseDensity, - dPhaseDensity_dPressure, - dPhaseDensity_dTemperature, - dPhaseDensity_dGlobalCompFraction - }; - - CompositionalVarContainer< 1 > phaseMassDens { - phaseMassDensity, - dPhaseMassDensity_dPressure, - dPhaseMassDensity_dTemperature, - dPhaseMassDensity_dGlobalCompFraction - }; - - CompositionalVarContainer< 1 > phaseVisc { - phaseViscosity, - dPhaseViscosity_dPressure, - dPhaseViscosity_dTemperature, - dPhaseViscosity_dGlobalCompFraction - }; - - CompositionalVarContainer< 2 > phaseCompFrac { - phaseCompFraction, - dPhaseCompFraction_dPressure, - dPhaseCompFraction_dTemperature, - dPhaseCompFraction_dGlobalCompFraction - }; - - CompositionalVarContainer< 0 > totalDens { - totalDensity, - dTotalDensity_dPressure, - dTotalDensity_dTemperature, - dTotalDensity_dGlobalCompFraction - }; - -#if defined(__CUDACC__) - // For some reason nvcc thinks these aren't used. - GEOSX_UNUSED_VAR( phaseFrac, phaseDens, phaseMassDens, phaseVisc, phaseCompFrac, totalDens ); -#endif - - constexpr localIndex numComps = 2; - constexpr localIndex numPhases = 2; - localIndex const ipGas = m_phaseGasIndex; - localIndex const ipLiq = m_phaseLiquidIndex; - - // 1. Convert input mass fractions to mole fractions and keep derivatives - - stackArray1d< real64, numComps > compMoleFrac( numComps ); - stackArray2d< real64, numComps *numComps > dCompMoleFrac_dCompMassFrac( numComps, numComps ); - - if( m_useMass ) - { - real64 totalMolality = 0.0; - for( localIndex ic = 0; ic < numComps; ++ic ) - { - real64 const mwInv = 1.0 / m_componentMolarWeight[ic]; - compMoleFrac[ic] = composition[ic] * mwInv; // this is molality (units of mole/mass) - dCompMoleFrac_dCompMassFrac[ic][ic] = mwInv; - totalMolality += compMoleFrac[ic]; - } - - real64 const totalMolalityInv = 1.0 / totalMolality; - for( localIndex ic = 0; ic < numComps; ++ic ) - { - compMoleFrac[ic] *= totalMolalityInv; - - for( localIndex jc = 0; jc < numComps; ++jc ) - { - dCompMoleFrac_dCompMassFrac[ic][jc] -= compMoleFrac[ic] / m_componentMolarWeight[jc]; - dCompMoleFrac_dCompMassFrac[ic][jc] *= totalMolalityInv; - } - } - } - else - { - for( localIndex ic = 0; ic < numComps; ++ic ) - { - compMoleFrac[ic] = composition[ic]; - } - } - - // 2. Compute phase fractions and phase component fractions - - real64 const temperatureInCelsius = temperature - 273.15; - m_co2SolubilityWrapper[0].compute( pressure, - temperatureInCelsius, - compMoleFrac, - phaseFrac.value, phaseFrac.dPres, phaseFrac.dTemp, phaseFrac.dComp, - phaseCompFrac.value, phaseCompFrac.dPres, phaseCompFrac.dTemp, phaseCompFrac.dComp ); - - // 3. Compute phase densities and phase viscosities - - m_co2DensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFrac.value[ipGas], - phaseDens.value[ipGas], phaseDens.dPres[ipGas], phaseDens.dTemp[ipGas], phaseDens.dComp[ipGas], - m_useMass ); - m_co2ViscosityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFrac.value[ipGas], - phaseVisc.value[ipGas], phaseVisc.dPres[ipGas], phaseVisc.dTemp[ipGas], phaseVisc.dComp[ipGas], - m_useMass ); - - m_brineDensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFrac.value[ipLiq], - phaseDens.value[ipLiq], phaseDens.dPres[ipLiq], phaseDens.dTemp[ipLiq], phaseDens.dComp[ipLiq], - m_useMass ); - m_brineViscosityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFrac.value[ipLiq], - phaseVisc.value[ipLiq], phaseVisc.dPres[ipLiq], phaseVisc.dTemp[ipLiq], phaseVisc.dComp[ipLiq], - m_useMass ); - - // 4. Depending on the m_useMass flag, convert to mass variables or simply compute mass density - - // TODO: for now the treatment of molar/mass density requires too many interpolations in the tables, it needs to be fixed - // we should modify the PVT functions so that they can return phaseMassDens, phaseDens, and phaseMW in one call - // TODO: extract the following piece of code and write a function that can be used here and in MultiFluidPVTPackageWrapper - - if( m_useMass ) - { - // 4.1. Convert phase fractions (requires two passes) - real64 totalMass{}; - real64 dTotalMass_dP{}; - real64 dTotalMass_dT{}; - real64 dTotalMass_dC[2]{}; - - // 4.1.0. Compute the phase molecular weights (ultimately, get that from the PVT function) - real64 phaseMW[2]{}; - real64 dPhaseMW_dPres[2]{}; - real64 dPhaseMW_dTemp[2]{}; - real64 dPhaseMW_dComp[2][2]{}; - real64 phaseMolarDens = 0.0; - real64 dPhaseMolarDens_dPres = 0.0; - real64 dPhaseMolarDens_dTemp = 0.0; - stackArray1d< real64, numComps > dPhaseMolarDens_dComp( 2 ); - m_co2DensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFrac.value[ipGas], - phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, - 0 ); - phaseMW[ipGas] = phaseDens.value[ipGas] / phaseMolarDens; - dPhaseMW_dPres[ipGas] = phaseDens.dPres[ipGas] / phaseMolarDens - phaseMW[ipGas]*dPhaseMolarDens_dPres / phaseMolarDens; - dPhaseMW_dTemp[ipGas] = phaseDens.dTemp[ipGas] / phaseMolarDens - phaseMW[ipGas]*dPhaseMolarDens_dTemp / phaseMolarDens; - for( localIndex ic = 0; ic < numComps; ++ic ) - { - dPhaseMW_dComp[ipGas][ic] = phaseDens.dComp[ipGas][ic] / phaseMolarDens - phaseMW[ipGas]*dPhaseMolarDens_dComp[ic] / phaseMolarDens; - } - m_brineDensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFrac.value[ipLiq], - phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, - 0 ); - phaseMW[ipLiq] = phaseDens.value[ipLiq] / phaseMolarDens; - dPhaseMW_dPres[ipLiq] = phaseDens.dPres[ipLiq] / phaseMolarDens - phaseMW[ipLiq]*dPhaseMolarDens_dPres / phaseMolarDens; - dPhaseMW_dTemp[ipLiq] = phaseDens.dTemp[ipLiq] / phaseMolarDens - phaseMW[ipLiq]*dPhaseMolarDens_dTemp / phaseMolarDens; - for( localIndex ic = 0; ic < numComps; ++ic ) - { - dPhaseMW_dComp[ipLiq][ic] = phaseDens.dComp[ipLiq][ic] / phaseMolarDens - phaseMW[ipLiq]*dPhaseMolarDens_dComp[ic]/phaseMolarDens; - } - - - // 4.1.1. Compute mass of each phase and total mass (on a 1-mole basis) - for( localIndex ip = 0; ip < numPhases; ++ip ) - { - real64 const nu = phaseFrac.value[ip]; - - phaseFrac.value[ip] *= phaseMW[ip]; - phaseFrac.dPres[ip] = phaseFrac.dPres[ip] * phaseMW[ip] + nu * dPhaseMW_dPres[ip]; - phaseFrac.dTemp[ip] = phaseFrac.dTemp[ip] * phaseMW[ip] + nu * dPhaseMW_dTemp[ip]; - - totalMass += phaseFrac.value[ip]; - dTotalMass_dP += phaseFrac.dPres[ip]; - dTotalMass_dT += phaseFrac.dTemp[ip]; - - for( localIndex jc = 0; jc < numComps; ++jc ) - { - phaseFrac.dComp[ip][jc] = phaseFrac.dComp[ip][jc] * phaseMW[ip] + nu * dPhaseMW_dComp[ip][jc]; - dTotalMass_dC[jc] += phaseFrac.dComp[ip][jc]; - } - } - - // 4.1.2. Normalize to get mass fractions - real64 const totalMassInv = 1.0 / totalMass; - for( localIndex ip = 0; ip < numPhases; ++ip ) - { - phaseFrac.value[ip] *= totalMassInv; - phaseFrac.dPres[ip] = ( phaseFrac.dPres[ip] - phaseFrac.value[ip] * dTotalMass_dP ) * totalMassInv; - phaseFrac.dTemp[ip] = ( phaseFrac.dTemp[ip] - phaseFrac.value[ip] * dTotalMass_dT ) * totalMassInv; - - for( localIndex jc = 0; jc < numComps; ++jc ) - { - phaseFrac.dComp[ip][jc] = ( phaseFrac.dComp[ip][jc] - phaseFrac.value[ip] * dTotalMass_dC[jc] ) * totalMassInv; - } - } - - // 4.2. Convert phase compositions - for( localIndex ip = 0; ip < numPhases; ++ip ) - { - real64 const phaseMWInv = 1.0 / phaseMW[ip]; - - for( localIndex ic = 0; ic < numComps; ++ic ) - { - - real64 const compMW = m_componentMolarWeight[ic]; - - phaseCompFrac.value[ip][ic] = phaseCompFrac.value[ip][ic] * compMW * phaseMWInv; - phaseCompFrac.dPres[ip][ic] = - ( phaseCompFrac.dPres[ip][ic] * compMW - phaseCompFrac.value[ip][ic] * dPhaseMW_dPres[ip] ) * phaseMWInv; - phaseCompFrac.dTemp[ip][ic] = - ( phaseCompFrac.dTemp[ip][ic] * compMW - phaseCompFrac.value[ip][ic] * dPhaseMW_dTemp[ip] ) * phaseMWInv; - - for( localIndex jc = 0; jc < numComps; ++jc ) - { - phaseCompFrac.dComp[ip][ic][jc] = - ( phaseCompFrac.dComp[ip][ic][jc] * compMW - phaseCompFrac.value[ip][ic] * dPhaseMW_dComp[ip][jc] ) * phaseMWInv; - } - } - } - - // 4.3. Update derivatives w.r.t. mole fractions to derivatives w.r.t mass fractions - real64 work[numComps]{}; - for( localIndex ip = 0; ip < numPhases; ++ip ) - { - applyChainRuleInPlace( numComps, dCompMoleFrac_dCompMassFrac, phaseFrac.dComp[ip], work ); - applyChainRuleInPlace( numComps, dCompMoleFrac_dCompMassFrac, phaseDens.dComp[ip], work ); - - for( localIndex ic = 0; ic < numComps; ++ic ) - { - applyChainRuleInPlace( numComps, dCompMoleFrac_dCompMassFrac, phaseCompFrac.dComp[ip][ic], work ); - } - } - - // 4.4 Copy the phase densities into the phase mass densities - for( localIndex ip = 0; ip < numPhases; ++ip ) - { - phaseMassDens.value[ip] = phaseDens.value[ip]; - phaseMassDens.dPres[ip] = phaseDens.dPres[ip]; - phaseMassDens.dTemp[ip] = phaseDens.dTemp[ip]; - for( localIndex ic = 0; ic < numComps; ++ic ) - { - phaseMassDens.dComp[ip][ic] = phaseDens.dComp[ip][ic]; - } - } - } - else - { - // for now, we have to compute the phase mass density here - m_co2DensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFrac.value[ipGas], - phaseMassDens.value[ipGas], phaseMassDens.dPres[ipGas], - phaseMassDens.dTemp[ipGas], phaseMassDens.dComp[ipGas], - true ); - m_brineDensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFrac.value[ipLiq], - phaseMassDens.value[ipLiq], phaseMassDens.dPres[ipLiq], - phaseMassDens.dTemp[ipLiq], phaseMassDens.dComp[ipLiq], - true ); - } - - // TODO: extract the following piece of code and write a function that can be used here and in MultiFluidPVTPackageWrapper - - // 5. Compute total fluid mass/molar density and derivatives - { - totalDens.value = 0.0; - totalDens.dPres = 0.0; - totalDens.dTemp = 0.0; - for( localIndex jc = 0; jc < numComps; ++jc ) - { - totalDens.dComp[jc] = 0.0; - } - - // 5.1. Sum mass/molar fraction/density ratio over all phases to get the inverse of density - for( localIndex ip = 0; ip < numPhases; ++ip ) - { - real64 const densInv = 1.0 / phaseDens.value[ip]; - real64 const value = phaseFrac.value[ip] * densInv; - - totalDens.value += value; - totalDens.dPres += ( phaseFrac.dPres[ip] - value * phaseDens.dPres[ip] ) * densInv; - totalDens.dTemp += ( phaseFrac.dTemp[ip] - value * phaseDens.dTemp[ip] ) * densInv; - - for( localIndex jc = 0; jc < numComps; ++jc ) - { - totalDens.dComp[jc] += ( phaseFrac.dComp[ip][jc] - value * phaseDens.dComp[ip][jc] ) * densInv; - } - } - - // 5.2. Invert the previous quantity to get actual density - totalDens.value = 1.0 / totalDens.value; - real64 const minusDens2 = -totalDens.value * totalDens.value; - totalDens.dPres *= minusDens2; - totalDens.dTemp *= minusDens2; - - for( localIndex jc = 0; jc < numComps; ++jc ) - { - totalDens.dComp[jc] *= minusDens2; - } - } -} - -} //namespace constitutive - -} //namespace geosx - -#endif //GEOSX_CONSTITUTIVE_FLUID_NEWMULTIPHASEMULTICOMPONENTFLUID_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp index 5ca29d67ec1..d6aea010dcb 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp @@ -13,11 +13,14 @@ */ /** - * @file BrineCO2DensityFunction.cpp + * @file BrineCO2Density.cpp */ #include "constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp" +#include "managers/Functions/FunctionManager.hpp" +#include "managers/GeosxState.hpp" + namespace geosx { @@ -26,69 +29,57 @@ using namespace stringutilities; namespace PVTProps { -BrineCO2DensityFunction::BrineCO2DensityFunction( string_array const & inputPara, - string_array const & componentNames, - real64_array const & componentMolarWeight ): - PVTFunction( inputPara[1], componentNames, componentMolarWeight ) +BrineCO2Density::BrineCO2Density( array1d< string > const & inputPara, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ): + PVTFunctionBase( inputPara[1], + componentNames, + componentMolarWeight ) { - bool notFound = 1; - + bool notFound = true; for( localIndex i = 0; i < componentNames.size(); ++i ) { - - if( streq( componentNames[i], "CO2" ) || streq( componentNames[i], "co2" )) + if( componentNames[i] == "CO2" || componentNames[i] == "co2" ) { m_CO2Index = i; - notFound = 0; + notFound = false; break; } - } - GEOSX_ERROR_IF( notFound, "Component CO2 is not found!" ); - notFound = 1; - + notFound = true; for( localIndex i = 0; i < componentNames.size(); ++i ) { - - if( streq( componentNames[i], "Water" ) || streq( componentNames[i], "water" )) + if( componentNames[i] == "Water" || componentNames[i] == "water" ) { m_waterIndex = i; - notFound = 0; + notFound = false; break; } - } - GEOSX_ERROR_IF( notFound, "Component Water/Brine is not found!" ); - makeTable( inputPara ); } -void BrineCO2DensityFunction::makeTable( string_array const & inputPara ) +void BrineCO2Density::makeTable( array1d< string > const & inputPara ) { - real64_array pressures; - real64_array temperatures; - - real64 PStart, PEnd, dP; - real64 TStart, TEnd, dT; - real64 P, T, m; - - dT = -1.0; - dP = -1.0; - TStart = -1.0; - TEnd = -1.0; - PStart = -1.0; - PEnd = -1.0; + array1d< array1d< real64 > > coordinates; + coordinates.resize( 2 ); + real64 TStart = -1.0; + real64 TEnd = -1.0; + real64 dT = -1.0; + real64 PStart = -1.0; + real64 PEnd = -1.0; + real64 dP = -1.0; + real64 salinity = 0.0; GEOSX_ERROR_IF( inputPara.size() < 9, "Invalid BrineCO2Density input!" ); try { - PStart = stod( inputPara[2] ); PEnd = stod( inputPara[3] ); dP = stod( inputPara[4] ); @@ -97,93 +88,46 @@ void BrineCO2DensityFunction::makeTable( string_array const & inputPara ) TEnd = stod( inputPara[6] ); dT = stod( inputPara[7] ); - m = stod( inputPara[8] ); - + salinity = stod( inputPara[8] ); } catch( const std::invalid_argument & e ) { - - GEOSX_ERROR( "Invalid BrineCO2Density argument:" + string( e.what())); - + GEOSX_ERROR( "Invalid BrineCO2Density argument:" + string( e.what()) ); } - P = PStart; - + real64 P = PStart; while( P <= PEnd ) { - - pressures.emplace_back( P ); + coordinates[0].emplace_back( P ); P += dP; - } - T = TStart; - + real64 T = TStart; while( T <= TEnd ) { - - temperatures.emplace_back( T ); + coordinates[1].emplace_back( T ); T += dT; - } - localIndex const nP = pressures.size(); - localIndex const nT = temperatures.size(); - - real64_array2d densities( nP, nT ); - - calculateBrineDensity( pressures, temperatures, m, densities ); + localIndex const nP = coordinates[0].size(); + localIndex const nT = coordinates[1].size(); - m_BrineDensityTable = std::make_shared< XYTable >( "BrineDensityTable", pressures, temperatures, densities ); -} - - -void BrineCO2DensityFunction::evaluation( EvalVarArgs const & pressure, EvalVarArgs const & temperature, - arraySlice1d< EvalVarArgs const > const & phaseComposition, EvalVarArgs & value, bool useMass ) const -{ - EvalArgs2D P, T, density; - P.m_var = pressure.m_var; - P.m_der[0] = 1.0; - - T.m_var = temperature.m_var; - T.m_der[1] = 1.0; - - density = m_BrineDensityTable->value( P, T ); - - constexpr real64 a = 37.51; - constexpr real64 b = -9.585e-2; - constexpr real64 c = 8.740e-4; - constexpr real64 d = -5.044e-7; - - real64 temp = T.m_var; - - real64 const V = (a + b * temp + c * temp * temp + d * temp * temp * temp) * 1e-6; - - real64 const CO2MW = m_componentMolarWeight[m_CO2Index]; - real64 const waterMW = m_componentMolarWeight[m_waterIndex]; - - EvalVarArgs den, C, X; - - den.m_var = density.m_var; - den.m_der[0] = density.m_der[0]; + array1d< real64 > values( nP * nT ); + calculateBrineDensity( coordinates, salinity, values ); - X = phaseComposition[m_CO2Index]; - - C = X * den / (waterMW * (1.0 - X)); - - if( useMass ) - { - value = den + CO2MW * C - C * den * V; - } - else - { - value = den / waterMW + C - C * den * V / waterMW; - } + FunctionManager & functionManager = getGlobalState().getFunctionManager(); + m_brineDensityTable = dynamicCast< TableFunction * >( functionManager.createChild( "TableFunction", "brineDensityTable" ) ); + m_brineDensityTable->setTableCoordinates( coordinates ); + m_brineDensityTable->setTableValues( values ); + m_brineDensityTable->reInitializeFunction(); + m_brineDensityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); } -void BrineCO2DensityFunction::calculateBrineDensity( real64_array const & pressure, real64_array const & temperature, real64 const & salinity, - real64_array2d const & density ) +void BrineCO2Density::calculateBrineDensity( array1d< array1d< real64 > > const & coordinates, + real64 const & salinity, + array1d< real64 > const & values ) { + // these coefficients come from Phillips et al. (1981), equations (4) and (5), pages 14 and 15 constexpr real64 c1 = -9.9595; constexpr real64 c2 = 7.0845; constexpr real64 c3 = 3.9093; @@ -197,25 +141,35 @@ void BrineCO2DensityFunction::calculateBrineDensity( real64_array const & pressu constexpr real64 CC = -8.750567; constexpr real64 DD = 2.663107; - real64 P, x; + localIndex const numPressures = coordinates[0].size(); + localIndex const numTemperatures = coordinates[1].size(); - for( localIndex i = 0; i < pressure.size(); ++i ) + for( localIndex i = 0; i < numPressures; ++i ) { + real64 const P = coordinates[0][i] / 1e5; - P = pressure[i] / 1e5; - - for( localIndex j = 0; j < temperature.size(); ++j ) + for( localIndex j = 0; j < numTemperatures; ++j ) { - x = c1 * exp( a1 * salinity ) + c2 * exp( a2 * temperature[j] ) + c3 * exp( a3 * P ); - - density[i][j] = (AA + BB * x + CC * x * x + DD * x * x * x) * 1000.0; + // see Phillips et al. (1981), equations (4) and (5), pages 14 and 15 + real64 const x = c1 * exp( a1 * salinity ) + + c2 * exp( a2 * coordinates[1][j] ) + + c3 * exp( a3 * P ); + values[j*numPressures+i] = (AA + BB * x + CC * x * x + DD * x * x * x) * 1000.0; } } } -REGISTER_CATALOG_ENTRY( PVTFunction, - BrineCO2DensityFunction, - string_array const &, string_array const &, real64_array const & ) +BrineCO2Density::KernelWrapper BrineCO2Density::createKernelWrapper() +{ + return KernelWrapper( m_componentNames, + m_componentMolarWeight, + m_brineDensityTable, + m_CO2Index, + m_waterIndex ); +} + +REGISTER_CATALOG_ENTRY( PVTFunctionBase, BrineCO2Density, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) } // namespace PVTProps + } // namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp index 911fda1c026..072f2c10dc0 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp @@ -13,62 +13,217 @@ */ /** - * @file BrineCO2DensityFunction.hpp + * @file BrineCO2Density.hpp */ -#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINECO2DENSITYFUNCTION_HPP_ -#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINECO2DENSITYFUNCTION_HPP_ +#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINECO2DENSITY_HPP_ +#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINECO2DENSITY_HPP_ #include "PVTFunctionBase.hpp" +#include "managers/Functions/TableFunction.hpp" + namespace geosx { namespace PVTProps { -class BrineCO2DensityFunction : public PVTFunction +class BrineCO2DensityUpdate final : public PVTFunctionBaseUpdate { public: - BrineCO2DensityFunction( string_array const & inputPara, - string_array const & componentNames, - real64_array const & componentMolarWeight ); - ~BrineCO2DensityFunction() override {} + BrineCO2DensityUpdate( arrayView1d< string const > const & componentNames, + arrayView1d< real64 const > const & componentMolarWeight, + TableFunction * brineDensityTable, + localIndex const CO2Index, + localIndex const waterIndex ) + : PVTFunctionBaseUpdate( componentNames, + componentMolarWeight ), + m_brineDensityTable( brineDensityTable->createKernelWrapper() ), + m_CO2Index( CO2Index ), + m_waterIndex( waterIndex ) + {} + /// Default copy constructor + BrineCO2DensityUpdate( BrineCO2DensityUpdate const & ) = default; - static constexpr auto m_catalogName = "BrineCO2Density"; - static string catalogName() { return m_catalogName; } - virtual string getCatalogName() const override final { return catalogName(); } + /// Default move constructor + BrineCO2DensityUpdate( BrineCO2DensityUpdate && ) = default; + /// Deleted copy assignment operator + BrineCO2DensityUpdate & operator=( BrineCO2DensityUpdate const & ) = delete; - virtual PVTFuncType functionType() const override - { - return PVTFuncType::DENSITY; + /// Deleted move assignment operator + BrineCO2DensityUpdate & operator=( BrineCO2DensityUpdate && ) = delete; + + GEOSX_HOST_DEVICE + GEOSX_FORCE_INLINE + virtual void compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & phaseComposition, + real64 & value, + real64 & dValue_dPressure, + real64 & dValue_dTemperature, + arraySlice1d< real64 > const & dValue_dPhaseComposition, + bool useMass = 0 ) const override; + +protected: + + /// Table with brine density tabulated as a function (P,T,sal) + TableFunction::KernelWrapper const m_brineDensityTable; + + /// Index of the CO2 component + localIndex const m_CO2Index; + + /// Index of the water component + localIndex const m_waterIndex; + +}; + +class BrineCO2Density : public PVTFunctionBase +{ +public: + + BrineCO2Density( array1d< string > const & inputPara, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ); + + ~BrineCO2Density() override {} + static string catalogName() { return "BrineCO2Density"; } + + virtual string getCatalogName() const override final { return catalogName(); } + + virtual PVTFunctionType functionType() const override + { + return PVTFunctionType::DENSITY; } - virtual void evaluation( EvalVarArgs const & pressure, - EvalVarArgs const & temperature, - arraySlice1d< EvalVarArgs const > const & phaseComposition, - EvalVarArgs & value, - bool useMass = 0 ) const override; + /// Type of kernel wrapper for in-kernel update + using KernelWrapper = BrineCO2DensityUpdate; + + /** + * @brief Create an update kernel wrapper. + * @return the wrapper + */ + KernelWrapper createKernelWrapper(); private: - void makeTable( string_array const & inputPara ); + void makeTable( array1d< string > const & inputPara ); + + void calculateBrineDensity( array1d< array1d< real64 > > const & coordinates, + real64 const & salinity, + array1d< real64 > const & values ); - void calculateBrineDensity( real64_array const & pressure, real64_array const & temperature, real64 const & salinity, real64_array2d const & density ); + /// Table with brine density tabulated as a function of (P,T,sal) + TableFunction * m_brineDensityTable; - TableFunctionPtr m_BrineDensityTable; + /// Index of the CO2 phase localIndex m_CO2Index; + + /// Index of the water phase localIndex m_waterIndex; }; +GEOSX_HOST_DEVICE +GEOSX_FORCE_INLINE +void BrineCO2DensityUpdate::compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & phaseComposition, + real64 & value, + real64 & dValue_dPressure, + real64 & dValue_dTemperature, + arraySlice1d< real64 > const & dValue_dPhaseComposition, + bool useMass ) const +{ + // this method implements the method proposed by E. Garcia (2001) + + // these coefficients come from equation (2) from Garcia (2001) + constexpr real64 a = 37.51; + constexpr real64 b = -9.585e-2; + constexpr real64 c = 8.740e-4; + constexpr real64 d = -5.044e-7; + + real64 const input[2] = { pressure, temperature }; + real64 density = 0.0; + real64 densityDeriv[2]{}; + m_brineDensityTable.compute( input, density, densityDeriv ); + + // equation (2) from Garcia (2001) + real64 const squaredTemp = temperature * temperature; + real64 const V = ( a + + b * temperature + + c * squaredTemp + + d * squaredTemp * temperature ) * 1e-6; + real64 const dV_dTemp = ( b + + 2 * c * temperature + + 3 * d * squaredTemp ) * 1e-6; + + // CO2 concentration + real64 const denom = ( m_componentMolarWeight[m_waterIndex] * ( 1.0 - phaseComposition[m_CO2Index] ) ); + real64 const coef = phaseComposition[m_CO2Index] / denom; + real64 dCoef_dComp[2]{}; + dCoef_dComp[m_CO2Index] = 1.0 / denom; + dCoef_dComp[m_waterIndex] = -m_componentMolarWeight[m_waterIndex] * phaseComposition[m_CO2Index] / (denom * denom); + + real64 const conc = coef * density; + real64 const dConc_dPres = coef * densityDeriv[0]; + real64 const dConc_dTemp = coef * densityDeriv[1]; + real64 dConc_dComp[2]{}; + dConc_dComp[m_CO2Index] = dCoef_dComp[m_CO2Index] * density; + dConc_dComp[m_waterIndex] = dCoef_dComp[m_waterIndex] * density; + + // CO2 concentration times density times vol + real64 const concDensVol = conc * density * V; + real64 const dConcDensVol_dPres = ( dConc_dPres * density + conc * densityDeriv[0] ) * V; + real64 const dConcDensVol_dTemp = ( dConc_dTemp * density + conc * densityDeriv[1] ) * V + + conc * density * dV_dTemp; + real64 dConcDensVol_dComp[2]{}; + dConcDensVol_dComp[m_CO2Index] = dConc_dComp[m_CO2Index] * density * V; + dConcDensVol_dComp[m_waterIndex] = dConc_dComp[m_waterIndex] * density * V; + + // Brine density + // equation (1) from Garcia (2001) + if( useMass ) + { + value = density + + m_componentMolarWeight[m_CO2Index] * conc + - concDensVol; + dValue_dPressure = densityDeriv[0] + + m_componentMolarWeight[m_CO2Index] * dConc_dPres + - dConcDensVol_dPres; + dValue_dTemperature = densityDeriv[1] + + m_componentMolarWeight[m_CO2Index] * dConc_dTemp + - dConcDensVol_dTemp; + dValue_dPhaseComposition[m_CO2Index] = m_componentMolarWeight[m_CO2Index] * dConc_dComp[m_CO2Index] + - dConcDensVol_dComp[m_CO2Index]; + dValue_dPhaseComposition[m_waterIndex] = m_componentMolarWeight[m_CO2Index] * dConc_dComp[m_waterIndex] + - dConcDensVol_dComp[m_waterIndex]; + } + else + { + value = density / m_componentMolarWeight[m_waterIndex] + + conc + - concDensVol / m_componentMolarWeight[m_waterIndex]; + dValue_dPressure = densityDeriv[0] / m_componentMolarWeight[m_waterIndex] + + dConc_dPres + - dConcDensVol_dPres / m_componentMolarWeight[m_waterIndex]; + dValue_dTemperature = densityDeriv[1] / m_componentMolarWeight[m_waterIndex] + + dConc_dTemp + - dConcDensVol_dTemp / m_componentMolarWeight[m_waterIndex]; + dValue_dPhaseComposition[m_CO2Index] = dConc_dComp[m_CO2Index] + - dConcDensVol_dComp[m_CO2Index] / m_componentMolarWeight[m_waterIndex]; + dValue_dPhaseComposition[m_waterIndex] = dConc_dComp[m_waterIndex] + - dConcDensVol_dComp[m_waterIndex] / m_componentMolarWeight[m_waterIndex]; + } } -} +} // end namespace PVTProps + +} // end namespace geosx -#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINECO2DENSITYFUNCTION_HPP_ +#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINECO2DENSITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.cpp index 70eb081119a..e3046a34ece 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.cpp @@ -13,10 +13,9 @@ */ /** - * @file BrineViscosityFunction.cpp + * @file BrineViscosity.cpp */ - #include "constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp" namespace geosx @@ -27,25 +26,24 @@ using namespace stringutilities; namespace PVTProps { -BrineViscosityFunction::BrineViscosityFunction( string_array const & inputPara, - string_array const & componentNames, - real64_array const & componentMolarWeight ): - PVTFunction( inputPara[1], componentNames, componentMolarWeight ) +BrineViscosity::BrineViscosity( array1d< string > const & inputPara, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ): + PVTFunctionBase( inputPara[1], + componentNames, + componentMolarWeight ) { - - makeCoef( inputPara ); - + makeCoefficients( inputPara ); } -void BrineViscosityFunction::makeCoef( string_array const & inputPara ) +void BrineViscosity::makeCoefficients( array1d< string > const & inputPara ) { - + // these coefficients come from Phillips et al. (1981), equation (1), pages 5-6 constexpr real64 a = 0.0816; constexpr real64 b = 0.0122; constexpr real64 c = 0.000128; constexpr real64 d = 0.000629; constexpr real64 k = -0.7; - constexpr real64 waterVisc = 8.9e-4; //at 25C real64 m = -1.0; @@ -54,38 +52,27 @@ void BrineViscosityFunction::makeCoef( string_array const & inputPara ) try { - m = stod( inputPara[2] ); - } catch( const std::invalid_argument & e ) { - - GEOSX_ERROR( "Invalid BrineViscosity argument:" + string( e.what())); - + GEOSX_ERROR( "Invalid BrineViscosity argument:" + string( e.what() ) ); } - m_coef0 = (1.0 + a * m + b * m * m + c * m * m * m) * waterVisc; - m_coef1 = d * (1.0 - exp( k * m )) * waterVisc; - } - -void BrineViscosityFunction::evaluation( EvalVarArgs const & GEOSX_UNUSED_PARAM( - pressure ), EvalVarArgs const & temperature, arraySlice1d< EvalVarArgs const > const & GEOSX_UNUSED_PARAM( - phaseComposition ), EvalVarArgs & value, bool GEOSX_UNUSED_PARAM( useMass )) const +BrineViscosity::KernelWrapper BrineViscosity::createKernelWrapper() { - - value = m_coef0 + m_coef1 * temperature; - + return KernelWrapper( m_componentNames, + m_componentMolarWeight, + m_coef0, + m_coef1 ); } -REGISTER_CATALOG_ENTRY( PVTFunction, - BrineViscosityFunction, - string_array const &, string_array const &, real64_array const & ) +REGISTER_CATALOG_ENTRY( PVTFunctionBase, BrineViscosity, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) -} +} // end namespace PVTProps -} +} // end namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp index b6878c349ce..d7aa3351996 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp @@ -13,11 +13,11 @@ */ /** - * @file BrineViscosityFunction.hpp + * @file BrineViscosity.hpp */ -#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINEVISCOSITYFUNCTION_HPP_ -#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINEVISCOSITYFUNCTION_HPP_ +#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINEVISCOSITY_HPP_ +#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINEVISCOSITY_HPP_ #include "PVTFunctionBase.hpp" @@ -27,42 +27,116 @@ namespace geosx namespace PVTProps { -class BrineViscosityFunction : public PVTFunction +class BrineViscosityUpdate final : public PVTFunctionBaseUpdate { public: - - BrineViscosityFunction( string_array const & inputPara, - string_array const & componentNames, - real64_array const & componentMolarWeight ); - ~BrineViscosityFunction() override + BrineViscosityUpdate( arrayView1d< string const > const & componentNames, + arrayView1d< real64 const > const & componentMolarWeight, + real64 const & coef0, + real64 const & coef1 ) + : PVTFunctionBaseUpdate( componentNames, + componentMolarWeight ), + m_coef0( coef0 ), + m_coef1( coef1 ) {} - static constexpr auto m_catalogName = "BrineViscosity"; - static string catalogName() { return m_catalogName; } + /// Default copy constructor + BrineViscosityUpdate( BrineViscosityUpdate const & ) = default; + + /// Default move constructor + BrineViscosityUpdate( BrineViscosityUpdate && ) = default; + + /// Deleted copy assignment operator + BrineViscosityUpdate & operator=( BrineViscosityUpdate const & ) = delete; + + /// Deleted move assignment operator + BrineViscosityUpdate & operator=( BrineViscosityUpdate && ) = delete; + + GEOSX_HOST_DEVICE + GEOSX_FORCE_INLINE + virtual void compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & phaseComposition, + real64 & value, + real64 & dValue_dPressure, + real64 & dValue_dTemperature, + arraySlice1d< real64 > const & dValue_dPhaseComposition, + bool useMass = 0 ) const override; + +protected: + + real64 const m_coef0; + + real64 const m_coef1; + +}; + + +class BrineViscosity : public PVTFunctionBase +{ +public: + + BrineViscosity( array1d< string > const & inputPara, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ); + + ~BrineViscosity() override {} + + static string catalogName() { return "BrineViscosity"; } + virtual string getCatalogName() const override final { return catalogName(); } - virtual PVTFuncType functionType() const override + virtual PVTFunctionType functionType() const override { - return PVTFuncType::VISCOSITY; - + return PVTFunctionType::VISCOSITY; } - virtual void evaluation( EvalVarArgs const & pressure, - EvalVarArgs const & temperature, - arraySlice1d< EvalVarArgs const > const & phaseComposition, - EvalVarArgs & value, bool useMass = 0 ) const override; + /// Type of kernel wrapper for in-kernel update + using KernelWrapper = BrineViscosityUpdate; + + /** + * @brief Create an update kernel wrapper. + * @return the wrapper + */ + KernelWrapper createKernelWrapper(); private: - void makeCoef( string_array const & inputPara ); + void makeCoefficients( array1d< string > const & inputPara ); real64 m_coef0; + real64 m_coef1; }; +GEOSX_HOST_DEVICE +GEOSX_FORCE_INLINE +void BrineViscosityUpdate::compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & phaseComposition, + real64 & value, + real64 & dValue_dPressure, + real64 & dValue_dTemperature, + arraySlice1d< real64 > const & dValue_dPhaseComposition, + bool useMass ) const +{ + GEOSX_UNUSED_VAR( pressure ); + GEOSX_UNUSED_VAR( phaseComposition ); + GEOSX_UNUSED_VAR( useMass ); + + value = m_coef0 + m_coef1 * temperature; + dValue_dPressure = 0.0; + dValue_dTemperature = m_coef1; + for( real64 & val : dValue_dPhaseComposition ) + { + val = 0.0; + } } -} -#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINEVISCOSITYFUNCTION_HPP_ +} // end namespace PVTProps + +} // end namespace geosx + +#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINEVISCOSITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp index f8df2667523..2d7c24011d1 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp @@ -13,12 +13,14 @@ */ /** - * @file CO2SolubilityFunction.cpp + * @file CO2Solubility.cpp */ - #include "constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp" +#include "managers/Functions/FunctionManager.hpp" +#include "managers/GeosxState.hpp" + namespace geosx { @@ -28,244 +30,182 @@ using namespace stringutilities; namespace PVTProps { -constexpr real64 minForDivision = 1e-10; - -constexpr real64 T_K_f = 273.15; +constexpr real64 T_K_f = 273.15; constexpr real64 P_Pa_f = 1e+5; -constexpr real64 P_c = 73.773 * P_Pa_f; -constexpr real64 T_c = 304.1282; -constexpr real64 Rgas = 8.314467; -constexpr real64 V_c = Rgas*T_c/P_c; +constexpr real64 P_c = 73.773 * P_Pa_f; +constexpr real64 T_c = 304.1282; +constexpr real64 Rgas = 8.314467; +constexpr real64 V_c = Rgas*T_c/P_c; +// these coefficients are in Table (A1) of Duan and Sun (2003) constexpr real64 acoef[] = -{8.99288497e-2, -4.94783127e-1, 4.77922245e-2, 1.03808883e-2, -2.82516861e-2, 9.49887563e-2, 5.20600880e-4, -2.93540971e-4, -1.77265112e-3, -2.51101973e-5, - 8.93353441e-5, 7.88998563e-5, -1.66727022e-2, 1.398, 2.96e-2}; +{ 8.99288497e-2, -4.94783127e-1, 4.77922245e-2, 1.03808883e-2, -2.82516861e-2, 9.49887563e-2, 5.20600880e-4, + -2.93540971e-4, -1.77265112e-3, -2.51101973e-5, 8.93353441e-5, 7.88998563e-5, -1.66727022e-2, 1.398, 2.96e-2 }; +namespace detail +{ real64 ff( real64 const & T, real64 const & P, real64 const & V_r ) { + // reduced pressure real64 const P_r = P*P_Pa_f/P_c; + // reduced temperature real64 const T_r = (T_K_f+T)/T_c; - real64 const f_Z = 1.0 + (acoef[0] + acoef[1]/(T_r * T_r) + acoef[2]/(T_r*T_r*T_r))/V_r + (acoef[3] + acoef[4]/(T_r*T_r) + acoef[5]/(T_r*T_r*T_r))/(V_r*V_r) + - (acoef[6] + acoef[7]/(T_r*T_r) + acoef[8]/(T_r*T_r*T_r))/(V_r*V_r*V_r*V_r) + (acoef[9] + acoef[10]/(T_r*T_r) + acoef[11]/(T_r*T_r*T_r))/ - (V_r*V_r*V_r*V_r*V_r) + acoef[12]/(T_r*T_r*T_r)/(V_r*V_r) * (acoef[13] + acoef[14]/(V_r*V_r)) * exp( -acoef[14]/(V_r*V_r)) - P_r * V_r / - T_r; + // CO2 equation of state + // see equation (A1) in Duan and Sun (2003) + real64 const f_Z = 1.0 + + ( acoef[0] + acoef[1]/(T_r * T_r) + acoef[2]/(T_r * T_r * T_r) )/V_r + + ( acoef[3] + acoef[4]/(T_r * T_r) + acoef[5]/(T_r * T_r * T_r) )/(V_r*V_r) + + ( acoef[6] + acoef[7]/(T_r * T_r) + acoef[8]/(T_r * T_r * T_r) )/(V_r*V_r*V_r*V_r) + + ( acoef[9] + acoef[10]/(T_r * T_r) + acoef[11]/(T_r * T_r * T_r) )/(V_r*V_r*V_r*V_r*V_r) + + acoef[12]/(T_r * T_r * T_r)/(V_r * V_r) * (acoef[13] + acoef[14]/(V_r * V_r)) * exp( -acoef[14]/(V_r * V_r)) - P_r * V_r / T_r; return f_Z; } real64 PWater( real64 const & T ) { - constexpr real64 ccoef[] = {-38.640844, 5.8948420, 59.876516, 26.654627, 10.637097}; - - real64 const P_c_w = 220.85; // H2O critical pressure (bars) - real64 const T_c_w = 647.29; // H2O critical temperature (K) - real64 const tt = ((T+T_K_f)-T_c_w)/T_c_w; - real64 const x = (P_c_w*(T+T_K_f)/T_c_w) * (1 + ccoef[0]*pow( -tt, 1.9 ) + ccoef[1]*tt + ccoef[2]*tt*tt + ccoef[3]*tt*tt*tt + ccoef[4]*tt*tt*tt*tt); + // these coefficients are defined in Table (B1) of Duan and Sun (2003) + constexpr real64 ccoef[] = { -38.640844, 5.8948420, 59.876516, 26.654627, 10.637097 }; + + // H2O critical pressure (bars) + real64 const P_c_w = 220.85; + // H2O critical temperature (K) + real64 const T_c_w = 647.29; + real64 const tt = ( (T+T_K_f)-T_c_w )/T_c_w; + // Empirical model for water pressure of equation (B1) of Duan and Sun (2003) + real64 const x = (P_c_w*(T+T_K_f)/T_c_w) + * (1 + + ccoef[0]*pow( -tt, 1.9 ) + + ccoef[1]*tt + + ccoef[2]*tt*tt + + ccoef[3]*tt*tt*tt + + ccoef[4]*tt*tt*tt*tt); return x; } real64 logF( real64 const & T, real64 const & P, real64 const & V_r ) { + // reduced pressure real64 const P_r = P*P_Pa_f/P_c; + // reduced temperature real64 const T_r = (T_K_f+T)/T_c; + real64 const Z = P_r * V_r/T_r; - real64 const Z=P_r * V_r/T_r; - - real64 const log_f = Z - 1 - log( Z ) + (acoef[0] + acoef[1]/T_r/T_r + acoef[2]/T_r/T_r/T_r)/V_r + (acoef[3] + acoef[4]/T_r/T_r + acoef[5]/T_r/T_r/T_r)/2.0/ - V_r/V_r + (acoef[6] + acoef[7]/T_r/T_r + acoef[8]/T_r/T_r/T_r)/4.0/V_r/V_r/V_r/V_r + - (acoef[9] + acoef[10]/T_r/T_r + acoef[11]/T_r/T_r/T_r)/5.0/V_r/V_r/ - V_r/V_r/V_r + acoef[12]/2.0/T_r/T_r/T_r/acoef[14] * - (acoef[13] + 1.0 - (acoef[13] + 1.0 + acoef[14]/V_r/V_r) * exp( -acoef[14]/V_r/V_r )); + // fugacity coefficient of CO2, equation (A6) of Duan and Sun (2003) + real64 const log_f = Z - 1 - log( Z ) + + ( acoef[0] + acoef[1]/T_r/T_r + acoef[2]/T_r/T_r/T_r )/V_r + + ( acoef[3] + acoef[4]/T_r/T_r + acoef[5]/T_r/T_r/T_r )/2.0/V_r/V_r + + ( acoef[6] + acoef[7]/T_r/T_r + acoef[8]/T_r/T_r/T_r )/4.0/V_r/V_r/V_r/V_r + + ( acoef[9] + acoef[10]/T_r/T_r + acoef[11]/T_r/T_r/T_r )/5.0/V_r/V_r/V_r/V_r/V_r + + acoef[12]/2.0/T_r/T_r/T_r/acoef[14] * ( acoef[13] + 1.0 - (acoef[13] + 1.0 + acoef[14]/V_r/V_r) * exp( -acoef[14]/V_r/V_r ) ); return log_f; } real64 Par( real64 const & T, real64 const & P, real64 const * cc ) { - real64 x = cc[0] + cc[1]*T +cc[2]/T + cc[3]*T*T + cc[4]/(630.0-T) + cc[5]*P + cc[6] *P *log( T ) + cc[7]*P/T + cc[8]*P/(630.0-T) + cc[9]*P*P/(630.0-T)/ - (630.0-T) + cc[10] *T *log( P ); + // "equation for the parameters", see equation (7) of Duan and Sun (2003) + real64 x = cc[0] + + cc[1]*T + + cc[2]/T + + cc[3]*T*T + + cc[4]/(630.0-T) + + cc[5]*P + + cc[6]*P *log( T ) + + cc[7]*P/T + + cc[8]*P/(630.0-T) + + cc[9]*P*P/(630.0-T)/(630.0-T) + + cc[10]*T *log( P ); return x; } -void CO2Solubility( real64 const & T, real64 const & P, real64 & V_r, real64 (*f)( real64 const & x1, real64 const & x2, real64 const & x3 )) -{ - - constexpr real64 eps = 1e-9; - int count = 0; - constexpr real64 dx = 1e-10; - - real64 dre; - real64 Vr_int = 0.05; - - V_r = 0.75*Rgas*(T_K_f+T)/(P*P_Pa_f)*(1/V_c); - - real64 v1, v0; - - for(;; ) - { - - if( V_r < 0.0 ) - { - V_r = Vr_int; - Vr_int += 0.05; - } - - v0 = (*f)( T, P, V_r ); - v1 = (*f)( T, P, V_r+dx ); - dre = -v0/((v1-v0)/dx); - - if( fabs( dre ) < eps ) - break; - - GEOSX_ERROR_IF( count > 50, "CO2Solubiltiy NR convergence fails! " << "dre = " << dre << ", eps = " << eps ); - - count++; - - V_r += dre; - } } -void CalculateCO2Solubility( real64_array const & pressure, real64_array const & temperature, real64 const & salinity, real64_array2d const & solubiltiy ) +CO2Solubility::CO2Solubility( array1d< string > const & inputPara, + array1d< string > const & phaseNames, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ): + FlashModelBase( inputPara[1], + componentNames, + componentMolarWeight ) { + GEOSX_ERROR_IF( phaseNames.size() != 2, "The CO2Solubility model is a two-phase model" ); + GEOSX_ERROR_IF( componentNames.size() != 2, "The CO2Solubility model is a two-component model" ); - real64 T, P, V_r, m, logK, y_CO2; - - constexpr real64 mu[] = - {28.9447706, -0.0354581768, -4770.67077, 1.02782768e-5, 33.8126098, 9.04037140e-3, -1.14934031e-3, -0.307405726, -0.0907301486, 9.32713393e-4, 0}; - - constexpr real64 lambda[] = {-0.411370585, 6.07632013e-4, 97.5347708, 0, 0, 0, 0, -0.0237622469, 0.0170656236, 0, 1.41335834e-5}; - - constexpr real64 zeta[] = {3.36389723e-4, -1.98298980e-5, 0, 0, 0, 0, 0, 2.12220830e-3, -5.24873303e-3, 0, 0}; - - m = salinity; - - for( localIndex i = 0; i < pressure.size(); ++i ) - { - - P = pressure[i] / P_Pa_f; - - for( localIndex j = 0; j < temperature.size(); ++j ) - { - - T = temperature[j]; - - CO2Solubility( T, P, V_r, &ff ); - - logK = Par( T+T_K_f, P, mu ) - logF( T, P, V_r ) + 2*Par( T+T_K_f, P, lambda )*m + Par( T+T_K_f, P, zeta )*m*m; - - y_CO2 = (P - PWater( T ))/P; - - solubiltiy[i][j] = y_CO2 * P / exp( logK ); - - } - - } - -} - - -CO2SolubilityFunction::CO2SolubilityFunction( string_array const & inputPara, - string_array const & phaseNames, - string_array const & componentNames, - real64_array const & componentMolarWeight ): - FlashModel( inputPara[1], componentNames, componentMolarWeight ) -{ - - bool notFound = 1; - + bool notFound = true; for( localIndex i = 0; i < componentNames.size(); ++i ) { - - if( streq( componentNames[i], "CO2" ) || streq( componentNames[i], "co2" )) + if( componentNames[i] == "CO2" || componentNames[i] == "co2" ) { m_CO2Index = i; - notFound = 0; + notFound = false; break; } - } - GEOSX_ERROR_IF( notFound, "Component CO2 is not found!" ); - notFound = 1; - + notFound = true; for( localIndex i = 0; i < componentNames.size(); ++i ) { - - if( streq( componentNames[i], "Water" ) || streq( componentNames[i], "water" )) + if( componentNames[i] == "Water" || componentNames[i] == "water" ) { m_waterIndex = i; - notFound = 0; + notFound = false; break; } - } - GEOSX_ERROR_IF( notFound, "Component Water/Brine is not found!" ); - - notFound = 1; - + notFound = true; for( localIndex i = 0; i < phaseNames.size(); ++i ) { - - if( streq( phaseNames[i], "CO2" ) || streq( phaseNames[i], "co2" ) || streq( phaseNames[i], "gas" ) || streq( phaseNames[i], "Gas" )) + if( phaseNames[i] == "CO2" || phaseNames[i] == "co2" || + phaseNames[i] == "gas" || phaseNames[i] == "Gas" ) { m_phaseGasIndex = i; - notFound = 0; + notFound = false; break; } - } - GEOSX_ERROR_IF( notFound, "Phase co2/gas is not found!" ); - notFound = 1; - + notFound = true; for( localIndex i = 0; i < phaseNames.size(); ++i ) { - - if( streq( phaseNames[i], "Water" ) || streq( phaseNames[i], "water" ) || streq( phaseNames[i], "Liquid" ) || streq( phaseNames[i], "liquid" )) + if( streq( phaseNames[i], "Water" ) || streq( phaseNames[i], "water" ) || + streq( phaseNames[i], "Liquid" ) || streq( phaseNames[i], "liquid" ) ) { m_phaseLiquidIndex = i; - notFound = 0; + notFound = false; break; } - } - GEOSX_ERROR_IF( notFound, "Phase water/liquid is not found!" ); makeTable( inputPara ); - } -void CO2SolubilityFunction::makeTable( string_array const & inputPara ) +void CO2Solubility::makeTable( array1d< string > const & inputPara ) { + array1d< array1d< real64 > > coordinates; + coordinates.resize( 2 ); - real64_array pressures; - real64_array temperatures; - - real64 PStart, PEnd, dP; - real64 TStart, TEnd, dT; - real64 P, T, m; - - dT = -1.0; - dP = -1.0; - TStart = -1.0; - TEnd = -1.0; - PStart = -1.0; - PEnd = -1.0; + real64 TStart = -1.0; + real64 TEnd = -1.0; + real64 dT = -1.0; + real64 PStart = -1.0; + real64 PEnd = -1.0; + real64 dP = -1.0; + real64 salinity = 0; GEOSX_ERROR_IF( inputPara.size() < 9, "Invalid CO2Solubility input!" ); try { - PStart = stod( inputPara[2] ); PEnd = stod( inputPara[3] ); dP = stod( inputPara[4] ); @@ -274,121 +214,131 @@ void CO2SolubilityFunction::makeTable( string_array const & inputPara ) TEnd = stod( inputPara[6] ); dT = stod( inputPara[7] ); - m = stod( inputPara[8] ); - + salinity = stod( inputPara[8] ); } catch( const std::invalid_argument & e ) { - - GEOSX_ERROR( "Invalid CO2Solubility argument:" + string( e.what())); - + GEOSX_ERROR( "Invalid CO2Solubility argument:" + string( e.what()) ); } - P = PStart; - + real64 P = PStart; while( P <= PEnd ) { - - pressures.emplace_back( P ); + coordinates[0].emplace_back( P ); P += dP; - } - T = TStart; - + real64 T = TStart; while( T <= TEnd ) { - - temperatures.emplace_back( T ); + coordinates[1].emplace_back( T ); T += dT; - } - localIndex const nP = pressures.size(); - localIndex const nT = temperatures.size(); - - real64_array2d solubilities( nP, nT ); - - CalculateCO2Solubility( pressures, temperatures, m, solubilities ); - - m_CO2SolubilityTable = std::make_shared< XYTable >( "CO2SolubilityTable", pressures, temperatures, solubilities ); - - + localIndex const nP = coordinates[0].size(); + localIndex const nT = coordinates[1].size(); + array1d< real64 > values( nP * nT ); + calculateCO2Solubility( coordinates, salinity, values ); + + FunctionManager & functionManager = getGlobalState().getFunctionManager(); + m_CO2SolubilityTable = dynamicCast< TableFunction * >( functionManager.createChild( "TableFunction", "CO2SolubilityTable" ) ); + m_CO2SolubilityTable->setTableCoordinates( coordinates ); + m_CO2SolubilityTable->setTableValues( values ); + m_CO2SolubilityTable->reInitializeFunction(); + m_CO2SolubilityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); } -void CO2SolubilityFunction::partition( EvalVarArgs const & pressure, EvalVarArgs const & temperature, arraySlice1d< EvalVarArgs const > const & compFraction, - arraySlice1d< EvalVarArgs > const & phaseFraction, arraySlice2d< EvalVarArgs > const & phaseCompFraction ) const +void CO2Solubility::calculateCO2Solubility( array1d< array1d< real64 > > const & coordinates, + real64 const & salinity, + array1d< real64 > const & values ) { + // Interaction parameters, see Table 2 of Duan and Sun (2003) + constexpr real64 mu[] = + { 28.9447706, -0.0354581768, -4770.67077, 1.02782768e-5, 33.8126098, 9.04037140e-3, + -1.14934031e-3, -0.307405726, -0.0907301486, 9.32713393e-4, 0 }; + constexpr real64 lambda[] = { -0.411370585, 6.07632013e-4, 97.5347708, 0, 0, 0, 0, -0.0237622469, 0.0170656236, 0, 1.41335834e-5 }; + constexpr real64 zeta[] = { 3.36389723e-4, -1.98298980e-5, 0, 0, 0, 0, 0, 2.12220830e-3, -5.24873303e-3, 0, 0 }; - EvalArgs2D P, T, solubility; - P.m_var = pressure.m_var; - P.m_der[0] = 1.0; + localIndex const numPressures = coordinates[0].size(); + localIndex const numTemperatures = coordinates[1].size(); - T.m_var = temperature.m_var; - T.m_der[1] = 1.0; + for( localIndex i = 0; i < numPressures; ++i ) + { + real64 const P = coordinates[0][i] / P_Pa_f; - //solubiltiy mol/kg(water) X = Csat/W - solubility = m_CO2SolubilityTable->value( P, T ); + for( localIndex j = 0; j < numTemperatures; ++j ) + { + real64 const T = coordinates[1][j]; - real64 const waterMW = m_componentMolarWeight[m_waterIndex]; + // compute reduced volume by solving the CO2 equation of state + real64 V_r = 0.0; + CO2SolubilityFunction( T, P, V_r, &detail::ff ); - solubility *= waterMW; + // compute equation (6) of Duan and Sun (2003) + real64 const logK = detail::Par( T+T_K_f, P, mu ) + - detail::logF( T, P, V_r ) + + 2*detail::Par( T+T_K_f, P, lambda ) * salinity + + detail::Par( T+T_K_f, P, zeta ) * salinity * salinity; - EvalVarArgs X, Y; + // mole fraction of CO2 in vapor phase, equation (4) of Duan and Sun (2003) + real64 const y_CO2 = (P - detail::PWater( T ))/P; + values[j*numPressures+i] = y_CO2 * P / exp( logK ); + } + } +} - X.m_var = solubility.m_var; - X.m_der[0] = solubility.m_der[0]; +void CO2Solubility::CO2SolubilityFunction( real64 const & T, + real64 const & P, + real64 & V_r, + real64 (*f)( real64 const & x1, real64 const & x2, real64 const & x3 ) ) +{ - //Y = C/W = z/(1-z) + constexpr real64 eps = 1e-9; + constexpr real64 dx = 1e-10; + int count = 0; + real64 Vr_int = 0.05; - if( compFraction[m_CO2Index].m_var > 1.0 - minForDivision ) - { - Y = compFraction[m_CO2Index] / minForDivision; - } - else - { - Y = compFraction[m_CO2Index] / (1.0 - compFraction[m_CO2Index]); - } + V_r = 0.75*Rgas*(T_K_f+T)/(P*P_Pa_f)*(1/V_c); - if( Y < X ) + // iterate until the solution of the CO2 equation of state is found + for(;; ) { - //liquid phase only - - phaseFraction[m_phaseLiquidIndex] = 1.0; - phaseFraction[m_phaseGasIndex] = 0.0; - - for( localIndex c = 0; c < m_componentNames.size(); ++c ) + if( V_r < 0.0 ) { - phaseCompFraction[m_phaseLiquidIndex][c] = compFraction[c]; + V_r = Vr_int; + Vr_int += 0.05; } - } - else - { - // two-phase - // liquid phase fraction = (Csat + W) / (C + W) = (Csat/W + 1) / (C/W + 1) - - phaseFraction[m_phaseLiquidIndex] = (X + 1.0)/ (Y + 1.0); - phaseFraction[m_phaseGasIndex] = 1.0 - phaseFraction[m_phaseLiquidIndex]; - - //liquid phase composition CO2 = Csat / (Csat + W) = (Csat/W) / (Csat/W + 1) + real64 const v0 = (*f)( T, P, V_r ); + real64 const v1 = (*f)( T, P, V_r+dx ); + real64 const dre = -v0/((v1-v0)/dx); - phaseCompFraction[m_phaseLiquidIndex][m_CO2Index] = X / (X + 1.0); - phaseCompFraction[m_phaseLiquidIndex][m_waterIndex] = 1.0 - phaseCompFraction[m_phaseLiquidIndex][m_CO2Index]; - - //gas phase composition CO2 = 1.0 + if( fabs( dre ) < eps ) + { + break; + } - phaseCompFraction[m_phaseGasIndex][m_CO2Index] = 1.0; - phaseCompFraction[m_phaseGasIndex][m_waterIndex] = 0.0; + GEOSX_ERROR_IF( count > 50, "CO2Solubility NR convergence fails! " << "dre = " << dre << ", eps = " << eps ); + count++; + V_r += dre; } } -REGISTER_CATALOG_ENTRY( FlashModel, - CO2SolubilityFunction, - string_array const &, string_array const &, string_array const &, real64_array const & ) - +CO2Solubility::KernelWrapper CO2Solubility::createKernelWrapper() +{ + return KernelWrapper( m_componentNames, + m_componentMolarWeight, + m_CO2SolubilityTable, + m_CO2Index, + m_waterIndex, + m_phaseGasIndex, + m_phaseLiquidIndex ); } -} +REGISTER_CATALOG_ENTRY( FlashModelBase, CO2Solubility, array1d< string > const &, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) + +} // end namespace PVTProps + +} // end namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp index 175e7d89424..147d6fb9ac5 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp @@ -13,55 +13,286 @@ */ /** - * @file CO2SolubilityFunction.hpp + * @file CO2Solubility.hpp */ -#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_CO2SOLUBILITYFUNCTION_HPP_ -#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_CO2SOLUBILITYFUNCTION_HPP_ +#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_CO2SOLUBILITY_HPP_ +#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_CO2SOLUBILITY_HPP_ #include "FlashModelBase.hpp" +#include "managers/Functions/TableFunction.hpp" + namespace geosx { namespace PVTProps { -class CO2SolubilityFunction : public FlashModel +constexpr real64 minForDivision = 1e-10; + +class CO2SolubilityUpdate final : public FlashModelBaseUpdate { public: - CO2SolubilityFunction( string_array const & inputPara, - string_array const & phaseNames, - string_array const & componentNames, - real64_array const & componentMolarWeight ); - - ~CO2SolubilityFunction() override + CO2SolubilityUpdate( arrayView1d< string const > const & componentNames, + arrayView1d< real64 const > const & componentMolarWeight, + TableFunction * CO2SolubilityTable, + localIndex const CO2Index, + localIndex const waterIndex, + localIndex const phaseGasIndex, + localIndex const phaseLiquidIndex ) + : FlashModelBaseUpdate( componentNames, + componentMolarWeight ), + m_CO2SolubilityTable( CO2SolubilityTable->createKernelWrapper() ), + m_CO2Index( CO2Index ), + m_waterIndex( waterIndex ), + m_phaseGasIndex( phaseGasIndex ), + m_phaseLiquidIndex( phaseLiquidIndex ) {} - static constexpr auto m_catalogName = "CO2Solubility"; - static string catalogName() { return m_catalogName; } + /// Default copy constructor + CO2SolubilityUpdate( CO2SolubilityUpdate const & ) = default; + + /// Default move constructor + CO2SolubilityUpdate( CO2SolubilityUpdate && ) = default; + + /// Deleted copy assignment operator + CO2SolubilityUpdate & operator=( CO2SolubilityUpdate const & ) = delete; + + /// Deleted move assignment operator + CO2SolubilityUpdate & operator=( CO2SolubilityUpdate && ) = delete; + + GEOSX_HOST_DEVICE + GEOSX_FORCE_INLINE + virtual void compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & compFraction, + arraySlice1d< real64 > const & phaseFraction, + arraySlice1d< real64 > const & dPhaseFraction_dPressure, + arraySlice1d< real64 > const & dPhaseFraction_dTemperature, + arraySlice2d< real64 > const & dPhaseFraction_dCompFraction, + arraySlice2d< real64 > const & phaseCompFraction, + arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, + arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, + arraySlice3d< real64 > const & dPhaseCompFraction_dCompFraction ) const; + +protected: + + /// Table with CO2 solubility tabulated as a function (P,T) + TableFunction::KernelWrapper const m_CO2SolubilityTable; + + /// Index of the CO2 phase + localIndex const m_CO2Index; + + /// Index of the water phase + localIndex const m_waterIndex; + + /// Index of the gas phase + localIndex const m_phaseGasIndex; + + /// Index of the liquid phase + localIndex const m_phaseLiquidIndex; + +}; + +class CO2Solubility : public FlashModelBase +{ +public: + + CO2Solubility( array1d< string > const & inputPara, + array1d< string > const & phaseNames, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ); + + ~CO2Solubility() override {} + + static string catalogName() { return "CO2Solubility"; } + virtual string getCatalogName() const override final { return catalogName(); } - virtual void partition( EvalVarArgs const & pressure, - EvalVarArgs const & temperature, - arraySlice1d< EvalVarArgs const > const & compFraction, - arraySlice1d< EvalVarArgs > const & phaseFraction, - arraySlice2d< EvalVarArgs > const & phaseCompFraction ) const override; + /// Type of kernel wrapper for in-kernel update + using KernelWrapper = CO2SolubilityUpdate; + + /** + * @brief Create an update kernel wrapper. + * @return the wrapper + */ + KernelWrapper createKernelWrapper(); private: - void makeTable( const string_array & inputPara ); + void makeTable( array1d< string > const & inputPara ); + + void calculateCO2Solubility( array1d< array1d< real64 > > const & coordinates, + real64 const & salinity, + array1d< real64 > const & values ); + + void CO2SolubilityFunction( real64 const & T, + real64 const & P, + real64 & V_r, + real64 (*f)( real64 const & x1, real64 const & x2, real64 const & x3 ) ); + + /// Table to compute solubility as a function of pressure and temperature + TableFunction * m_CO2SolubilityTable; - TableFunctionPtr m_CO2SolubilityTable; + /// Index of the CO2 component localIndex m_CO2Index; + + /// Index of the water component localIndex m_waterIndex; + + /// Index of the gas phase localIndex m_phaseGasIndex; + + /// Index of the liquid phase localIndex m_phaseLiquidIndex; }; -} +GEOSX_HOST_DEVICE +GEOSX_FORCE_INLINE +void CO2SolubilityUpdate::compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & compFraction, + arraySlice1d< real64 > const & phaseFraction, + arraySlice1d< real64 > const & dPhaseFraction_dPressure, + arraySlice1d< real64 > const & dPhaseFraction_dTemperature, + arraySlice2d< real64 > const & dPhaseFraction_dCompFraction, + arraySlice2d< real64 > const & phaseCompFraction, + arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, + arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, + arraySlice3d< real64 > const & dPhaseCompFraction_dCompFraction ) const +{ + // solubility mol/kg(water) X = Csat/W + real64 const input[2] = { pressure, temperature }; + real64 solubility = 0.0; + real64 solubilityDeriv[2]{}; + m_CO2SolubilityTable.compute( input, solubility, solubilityDeriv ); + + solubility *= m_componentMolarWeight[m_waterIndex]; + for( localIndex i = 0; i < 2; ++i ) + { + solubilityDeriv[i] *= m_componentMolarWeight[m_waterIndex]; + } + + real64 Y = 0.0; + real64 dY_dCompFrac[2]{}; + + // Y = C/W = z/(1-z) + + if( compFraction[m_CO2Index] > 1.0 - minForDivision ) + { + Y = compFraction[m_CO2Index] / minForDivision; + dY_dCompFrac[m_CO2Index] = (1.0 - compFraction[m_CO2Index]) / minForDivision; + dY_dCompFrac[m_waterIndex] = -compFraction[m_CO2Index] / minForDivision; + } + else + { + real64 const oneMinusCompFracInv = 1.0 / (1.0 - compFraction[m_CO2Index]); + Y = compFraction[m_CO2Index] * oneMinusCompFracInv; + dY_dCompFrac[m_CO2Index] = 1.0 * oneMinusCompFracInv; + dY_dCompFrac[m_waterIndex] = -compFraction[m_CO2Index] * oneMinusCompFracInv * oneMinusCompFracInv; + } + + if( Y < solubility ) + { + // liquid phase only + + // 1) Compute phase fractions + + phaseFraction[m_phaseLiquidIndex] = 1.0; + phaseFraction[m_phaseGasIndex] = 0.0; + for( real64 & val : dPhaseFraction_dPressure ) + { + val = 0.0; + } + for( real64 & val : dPhaseFraction_dTemperature ) + { + val = 0.0; + } + for( real64 & val : dPhaseFraction_dCompFraction ) + { + val = 0.0; + } + + // 2) Compute phase component fractions + for( localIndex ic = 0; ic < 2; ++ic ) + { + phaseCompFraction[m_phaseLiquidIndex][ic] = compFraction[ic]; + // the two following lines are not present in Yue's code, unclear if this will have some consequences + phaseCompFraction[m_phaseGasIndex][m_CO2Index] = 1.0; + phaseCompFraction[m_phaseGasIndex][m_waterIndex] = 0.0; + for( localIndex jc = 0; jc < 2; ++jc ) + { + dPhaseCompFraction_dCompFraction[m_phaseLiquidIndex][ic][jc] = + (ic == jc ) ? ( 1 - compFraction[ic] ) : -compFraction[ic]; + dPhaseCompFraction_dCompFraction[m_phaseGasIndex][ic][jc] = 0.0; + } + } + for( real64 & val : dPhaseCompFraction_dPressure ) + { + val = 0.0; + } + for( real64 & val : dPhaseCompFraction_dTemperature ) + { + val = 0.0; + } + + } + else + { + // two-phase flow + + // 1) Compute phase fractions + + // liquid phase fraction = (Csat + W) / (C + W) = (Csat/W + 1) / (C/W + 1) + real64 const onePlusYInv = 1.0 / ( 1.0 + Y ); + phaseFraction[m_phaseLiquidIndex] = (solubility + 1.0) * onePlusYInv; + dPhaseFraction_dPressure[m_phaseLiquidIndex] = solubilityDeriv[0] * onePlusYInv; + dPhaseFraction_dTemperature[m_phaseLiquidIndex] = solubilityDeriv[1] * onePlusYInv; + dPhaseFraction_dCompFraction[m_phaseLiquidIndex][m_CO2Index] = + -dY_dCompFrac[m_CO2Index] * phaseFraction[m_phaseLiquidIndex] * onePlusYInv; + dPhaseFraction_dCompFraction[m_phaseLiquidIndex][m_waterIndex] = + -dY_dCompFrac[m_waterIndex] * phaseFraction[m_phaseLiquidIndex] * onePlusYInv; + + phaseFraction[m_phaseGasIndex] = 1.0 - phaseFraction[m_phaseLiquidIndex]; + dPhaseFraction_dPressure[m_phaseGasIndex] = -dPhaseFraction_dPressure[m_phaseLiquidIndex]; + dPhaseFraction_dTemperature[m_phaseGasIndex] = -dPhaseFraction_dTemperature[m_phaseLiquidIndex]; + dPhaseFraction_dCompFraction[m_phaseGasIndex][m_CO2Index] = -dPhaseFraction_dCompFraction[m_phaseLiquidIndex][m_CO2Index]; + dPhaseFraction_dCompFraction[m_phaseGasIndex][m_waterIndex] = -dPhaseFraction_dCompFraction[m_phaseLiquidIndex][m_waterIndex]; + + // 2) Compute phase component fractions + + // liquid phase composition CO2 = Csat / (Csat + W) = (Csat/W) / (Csat/W + 1) + real64 const onePlusSolubilityInv = 1.0 / ( 1.0 + solubility ); + phaseCompFraction[m_phaseLiquidIndex][m_CO2Index] = solubility * onePlusSolubilityInv; + dPhaseCompFraction_dPressure[m_phaseLiquidIndex][m_CO2Index] = solubilityDeriv[0] * (onePlusSolubilityInv*onePlusSolubilityInv); + dPhaseCompFraction_dTemperature[m_phaseLiquidIndex][m_CO2Index] = solubilityDeriv[1] * (onePlusSolubilityInv*onePlusSolubilityInv); + + phaseCompFraction[m_phaseLiquidIndex][m_waterIndex] = 1.0 - phaseCompFraction[m_phaseLiquidIndex][m_CO2Index]; + dPhaseCompFraction_dPressure[m_phaseLiquidIndex][m_waterIndex] = -dPhaseCompFraction_dPressure[m_phaseLiquidIndex][m_CO2Index]; + dPhaseCompFraction_dTemperature[m_phaseLiquidIndex][m_waterIndex] = -dPhaseCompFraction_dTemperature[m_phaseLiquidIndex][m_CO2Index]; + + // gas phase composition CO2 = 1.0 + + phaseCompFraction[m_phaseGasIndex][m_CO2Index] = 1.0; + phaseCompFraction[m_phaseGasIndex][m_waterIndex] = 0.0; + dPhaseCompFraction_dPressure[m_phaseGasIndex][m_CO2Index] = 0.0; + dPhaseCompFraction_dPressure[m_phaseGasIndex][m_waterIndex] = 0.0; + dPhaseCompFraction_dTemperature[m_phaseGasIndex][m_CO2Index] = 0.0; + dPhaseCompFraction_dTemperature[m_phaseGasIndex][m_waterIndex] = 0.0; + + // phaseCompFraction does not depend on globalComponentFraction + for( real64 & val : dPhaseCompFraction_dCompFraction ) + { + val = 0.0; + } + } } -#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_CO2SOLUBILITYFUNCTION_HPP_ +} // end namespace PVTProps + +} // end namespace geosx + +#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_CO2SOLUBILITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp index 4ce0b2cb8d5..13d1804ea3a 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp @@ -13,12 +13,14 @@ */ /** - * @file FenghourCO2ViscosityFunction.cpp + * @file FenghourCO2Viscosity.cpp */ - #include "constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp" + #include "constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp" +#include "managers/Functions/FunctionManager.hpp" +#include "managers/GeosxState.hpp" namespace geosx { @@ -26,38 +28,32 @@ namespace geosx namespace PVTProps { -FenghourCO2ViscosityFunction::FenghourCO2ViscosityFunction( string_array const & inputPara, - string_array const & componentNames, - real64_array const & componentMolarWeight ): - PVTFunction( inputPara[1], componentNames, componentMolarWeight ) +FenghourCO2Viscosity::FenghourCO2Viscosity( array1d< string > const & inputPara, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ): + PVTFunctionBase( inputPara[1], + componentNames, + componentMolarWeight ) { - makeTable( inputPara ); - } -void FenghourCO2ViscosityFunction::makeTable( string_array const & inputPara ) +void FenghourCO2Viscosity::makeTable( array1d< string > const & inputPara ) { + array1d< array1d< real64 > > coordinates; + coordinates.resize( 2 ); - real64_array pressures; - real64_array temperatures; - - real64 PStart, PEnd, dP; - real64 TStart, TEnd, dT; - real64 P, T; - - dT = -1.0; - dP = -1.0; - TStart = -1.0; - TEnd = -1.0; - PStart = -1.0; - PEnd = -1.0; + real64 TStart = -1.0; + real64 TEnd = -1.0; + real64 dT = -1.0; + real64 PStart = -1.0; + real64 PEnd = -1.0; + real64 dP = -1.0; GEOSX_ERROR_IF( inputPara.size() < 8, "Invalid FenghourCO2Viscosity input!" ); try { - PStart = stod( inputPara[2] ); PEnd = stod( inputPara[3] ); dP = stod( inputPara[4] ); @@ -65,106 +61,104 @@ void FenghourCO2ViscosityFunction::makeTable( string_array const & inputPara ) TStart = stod( inputPara[5] ); TEnd = stod( inputPara[6] ); dT = stod( inputPara[7] ); - } catch( const std::invalid_argument & e ) { - - GEOSX_ERROR( "Invalid FenghourCO2Viscosity argument:" + string( e.what())); - + GEOSX_ERROR( "Invalid FenghourCO2Viscosity argument:" + string( e.what()) ); } - P = PStart; - + real64 P = PStart; while( P <= PEnd ) { - pressures.emplace_back( P ); + coordinates[0].emplace_back( P ); P += dP; } - T = TStart; - + real64 T = TStart; while( T <= TEnd ) { - temperatures.emplace_back( T ); + coordinates[1].emplace_back( T ); T += dT; } - localIndex nP = pressures.size(); - localIndex nT = temperatures.size(); - - real64_array2d viscosities( nP, nT ); - real64_array2d densities( nP, nT ); - - SpanWagnerCO2DensityFunction::calculateCO2Density( pressures, temperatures, densities ); - - calculateCO2Viscosity( pressures, temperatures, densities, viscosities ); - - m_CO2ViscosityTable = std::make_shared< XYTable >( "FenghourCO2ViscosityTable", pressures, temperatures, viscosities ); - + localIndex nP = coordinates[0].size(); + localIndex nT = coordinates[1].size(); + array1d< real64 > valuesDensity( nP * nT ); + array1d< real64 > valuesViscosity( nP * nT ); + SpanWagnerCO2Density::calculateCO2Density( coordinates, valuesDensity ); + calculateCO2Viscosity( coordinates, valuesDensity, valuesViscosity ); + + FunctionManager & functionManager = getGlobalState().getFunctionManager(); + m_CO2ViscosityTable = dynamicCast< TableFunction * >( functionManager.createChild( "TableFunction", "CO2ViscosityTable" ) ); + m_CO2ViscosityTable->setTableCoordinates( coordinates ); + m_CO2ViscosityTable->setTableValues( valuesViscosity ); + m_CO2ViscosityTable->reInitializeFunction(); + m_CO2ViscosityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); } -void FenghourCO2ViscosityFunction::evaluation( EvalVarArgs const & pressure, EvalVarArgs const & temperature, arraySlice1d< EvalVarArgs const > const & GEOSX_UNUSED_PARAM( - phaseComposition ), EvalVarArgs & value, bool GEOSX_UNUSED_PARAM( useMass )) const -{ - EvalArgs2D P, T, viscosity; - P.m_var = pressure.m_var; - P.m_der[0] = 1.0; - - T.m_var = temperature.m_var; - T.m_der[1] = 1.0; - - viscosity = m_CO2ViscosityTable->value( P, T ); - - value.m_var = viscosity.m_var; - value.m_der[0] = viscosity.m_der[0]; -} - -void FenghourCO2ViscosityFunction::fenghourCO2Viscosity( real64 const & Tcent, real64 const & den, real64 & vis ) +void FenghourCO2Viscosity::fenghourCO2ViscosityFunction( real64 const & temperatureCent, + real64 const & density, + real64 & viscosity ) { constexpr real64 espar = 251.196; constexpr real64 esparInv = 1.0 / espar; + // coefficients from Table (1) of Fenghour and Wakeham (1998) constexpr real64 aa[5] = { 0.235156, -0.491266, 5.211155e-2, 5.347906e-2, -1.537102e-2 }; + // coefficients from Table (3) of Fenghour and Wakeham (1998) constexpr real64 d11 = 0.4071119e-2; constexpr real64 d21 = 0.7198037e-4; constexpr real64 d64 = 0.2411697e-16; constexpr real64 d81 = 0.2971072e-22; constexpr real64 d82 = -0.1627888e-22; - - // temperature in Kelvin - const real64 Tkelvin = Tcent + 273.15; - // evaluate vlimit from eqns 3-5 - const real64 Tred = Tkelvin * esparInv; - const real64 x = log( Tred ); - const real64 lnGfun = aa[0] + x * (aa[1] + x * (aa[2] + x *(aa[3] + x * aa[4]))); - const real64 GfunInv = exp( -lnGfun ); - const real64 vlimit = 1.00697 * sqrt( Tkelvin ) * GfunInv; - - const real64 d2 = den * den; - const real64 vxcess = den * (d11 + den * (d21 + d2*d2*(d64 / (Tred*Tred*Tred) + d2*(d81 + d82/Tred)))); - + // we neglect critical viscosity constexpr real64 vcrit = 0.0; - vis = 1e-6 * (vlimit + vxcess + vcrit); + // temperature in Kelvin + real64 const temperatureKelvin = temperatureCent + 273.15; + // equation (5) of Fenghour and Wakeham (1998) + real64 const Tred = temperatureKelvin * esparInv; + real64 const x = log( Tred ); + // equation (4) of Fenghour and Wakeham (1998) + real64 const lnGfun = aa[0] + x * (aa[1] + x * (aa[2] + x *(aa[3] + x * aa[4]))); + real64 const GfunInv = exp( -lnGfun ); + // equation (3) of Fenghour and Wakeham (1998) + real64 const vlimit = 1.00697 * sqrt( temperatureKelvin ) * GfunInv; + + // equation (8) of Fenghour and Wakeham (1998) + real64 const d2 = density * density; + real64 const vxcess = density * (d11 + density * (d21 + d2*d2*(d64 / (Tred*Tred*Tred) + d2*(d81 + d82/Tred)))); + + // equation (1) of Fenghour and Wakeham (1998) + viscosity = 1e-6 * (vlimit + vxcess + vcrit); } -void FenghourCO2ViscosityFunction::calculateCO2Viscosity( real64_array const & pressure, real64_array const & temperature, real64_array2d const & density, - real64_array2d const & viscosity ) +void FenghourCO2Viscosity::calculateCO2Viscosity( array1d< array1d< real64 > > const & coordinates, + array1d< real64 > const & valuesDensity, + array1d< real64 > const & valuesViscosity ) { - for( localIndex i = 0; i < pressure.size(); ++i ) + localIndex const numPressures = coordinates[0].size(); + localIndex const numTemperatures = coordinates[1].size(); + + for( localIndex i = 0; i < numPressures; ++i ) { - for( localIndex j = 0; j < temperature.size(); ++j ) + for( localIndex j = 0; j < numTemperatures; ++j ) { - fenghourCO2Viscosity( temperature[j], density[i][j], viscosity[i][j] ); + fenghourCO2ViscosityFunction( coordinates[1][j], + valuesDensity[j*numPressures+i], + valuesViscosity[j*numPressures+i] ); } } } +FenghourCO2Viscosity::KernelWrapper FenghourCO2Viscosity::createKernelWrapper() +{ + return KernelWrapper( m_componentNames, + m_componentMolarWeight, + m_CO2ViscosityTable ); +} -REGISTER_CATALOG_ENTRY( PVTFunction, - FenghourCO2ViscosityFunction, - string_array const &, string_array const &, real64_array const & ) +REGISTER_CATALOG_ENTRY( PVTFunctionBase, FenghourCO2Viscosity, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) -} +} // end namespace PVTProps -} +} // end namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp index 20e173d16f9..dace097df5c 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp @@ -13,59 +13,136 @@ */ /** - * @file FenghourCO2ViscosityFunction.hpp + * @file FenghourCO2Viscosity.hpp */ -#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FENGHOURCO2VISCOSITYFUNCTION_HPP_ -#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FENGHOURCO2VISCOSITYFUNCTION_HPP_ +#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FENGHOURCO2VISCOSITY_HPP_ +#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FENGHOURCO2VISCOSITY_HPP_ #include "PVTFunctionBase.hpp" +#include "managers/Functions/TableFunction.hpp" + namespace geosx { namespace PVTProps { -class FenghourCO2ViscosityFunction : public PVTFunction +class FenghourCO2ViscosityUpdate final : public PVTFunctionBaseUpdate { public: - FenghourCO2ViscosityFunction( string_array const & inputPara, - string_array const & componentNames, - real64_array const & componentMolarWeight ); - ~FenghourCO2ViscosityFunction() override + FenghourCO2ViscosityUpdate( arrayView1d< string const > const & componentNames, + arrayView1d< real64 const > const & componentMolarWeight, + TableFunction * CO2ViscosityTable ) + : PVTFunctionBaseUpdate( componentNames, + componentMolarWeight ), + m_CO2ViscosityTable( CO2ViscosityTable->createKernelWrapper() ) {} - static constexpr auto m_catalogName = "FenghourCO2Viscosity"; - static string catalogName() { return m_catalogName; } + /// Default copy constructor + FenghourCO2ViscosityUpdate( FenghourCO2ViscosityUpdate const & ) = default; + + /// Default move constructor + FenghourCO2ViscosityUpdate( FenghourCO2ViscosityUpdate && ) = default; + + /// Deleted copy assignment operator + FenghourCO2ViscosityUpdate & operator=( FenghourCO2ViscosityUpdate const & ) = delete; + + /// Deleted move assignment operator + FenghourCO2ViscosityUpdate & operator=( FenghourCO2ViscosityUpdate && ) = delete; + + GEOSX_HOST_DEVICE + GEOSX_FORCE_INLINE + virtual void compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & phaseComposition, + real64 & value, + real64 & dValue_dPressure, + real64 & dValue_dTemperature, + arraySlice1d< real64 > const & dValue_dPhaseComposition, + bool useMass = 0 ) const override; + +protected: + + /// Table with viscosity tabulated as a function (P,T) + TableFunction::KernelWrapper const m_CO2ViscosityTable; + +}; + +class FenghourCO2Viscosity : public PVTFunctionBase +{ +public: + + FenghourCO2Viscosity( array1d< string > const & inputPara, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ); + ~FenghourCO2Viscosity() override {} + + static string catalogName() { return "FenghourCO2Viscosity"; } + virtual string getCatalogName() const override final { return catalogName(); } - virtual PVTFuncType functionType() const override + virtual PVTFunctionType functionType() const override { - return PVTFuncType::VISCOSITY; - + return PVTFunctionType::VISCOSITY; } - virtual void evaluation( EvalVarArgs const & pressure, - EvalVarArgs const & temperature, - arraySlice1d< EvalVarArgs const > const & phaseComposition, - EvalVarArgs & value, bool useMass = 0 ) const override; + /// Type of kernel wrapper for in-kernel update + using KernelWrapper = FenghourCO2ViscosityUpdate; + /** + * @brief Create an update kernel wrapper. + * @return the wrapper + */ + KernelWrapper createKernelWrapper(); private: - void makeTable( string_array const & inputPara ); + void makeTable( array1d< string > const & inputPara ); - void calculateCO2Viscosity( real64_array const & pressure, real64_array const & temperature, real64_array2d const & density, - real64_array2d const & viscosity ); + void calculateCO2Viscosity( array1d< array1d< real64 > > const & coordinates, + array1d< real64 > const & valuesDensity, + array1d< real64 > const & valuesViscosity ); - void fenghourCO2Viscosity( real64 const & Tcent, real64 const & den, real64 & vis ); + void fenghourCO2ViscosityFunction( real64 const & temperatureCent, + real64 const & density, + real64 & viscosity ); + + /// Table with CO2 viscosity tabulated as a function of (P,T) + TableFunction * m_CO2ViscosityTable; - TableFunctionPtr m_CO2ViscosityTable; }; -} +GEOSX_HOST_DEVICE +GEOSX_FORCE_INLINE +void FenghourCO2ViscosityUpdate::compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & phaseComposition, + real64 & value, + real64 & dValue_dPressure, + real64 & dValue_dTemperature, + arraySlice1d< real64 > const & dValue_dPhaseComposition, + bool useMass ) const +{ + GEOSX_UNUSED_VAR( phaseComposition ); + GEOSX_UNUSED_VAR( useMass ); + real64 const input[2] = { pressure, temperature }; + real64 densityDeriv[2]{}; + m_CO2ViscosityTable.compute( input, value, densityDeriv ); + dValue_dPressure = densityDeriv[0]; + dValue_dTemperature = densityDeriv[1]; + + for( real64 & val : dValue_dPhaseComposition ) + { + val = 0.0; + } } -#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FENGHOURCO2VISCOSITYFUNCTION_HPP_ + +} // end namespace PVTProps + +} // end namespace geosx + +#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FENGHOURCO2VISCOSITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/FlashModelBase.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/FlashModelBase.hpp index f65f4e2264e..15aa3067a78 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/FlashModelBase.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/FlashModelBase.hpp @@ -16,11 +16,11 @@ * @file FlashModelBase.hpp */ -#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FLASHMODELBASE_HPP_ -#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FLASHMODELBASE_HPP_ +#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWFLASHMODELBASE_HPP_ +#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWFLASHMODELBASE_HPP_ -#include "constitutive/fluid/PVTFunctions/UtilityFunctions.hpp" #include "codingUtilities/StringUtilities.hpp" +#include "dataRepository/ObjectCatalog.hpp" namespace geosx { @@ -28,57 +28,96 @@ namespace geosx namespace PVTProps { +class FlashModelBaseUpdate +{ +public: + + FlashModelBaseUpdate( arrayView1d< string const > const & componentNames, + arrayView1d< real64 const > const & componentMolarWeight ) + : + m_componentNames( componentNames ), + m_componentMolarWeight( componentMolarWeight ) + {} + + /// Default copy constructor + FlashModelBaseUpdate( FlashModelBaseUpdate const & ) = default; + + /// Default move constructor + FlashModelBaseUpdate( FlashModelBaseUpdate && ) = default; + + /// Deleted copy assignment operator + FlashModelBaseUpdate & operator=( FlashModelBaseUpdate const & ) = delete; + + /// Deleted move assignment operator + FlashModelBaseUpdate & operator=( FlashModelBaseUpdate && ) = delete; + + GEOSX_HOST_DEVICE + virtual void compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & compFraction, + arraySlice1d< real64 > const & phaseFraction, + arraySlice1d< real64 > const & dPhaseFraction_dPressure, + arraySlice1d< real64 > const & dPhaseFraction_dTemperature, + arraySlice2d< real64 > const & dPhaseFraction_dCompFraction, + arraySlice2d< real64 > const & phaseCompFraction, + arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, + arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, + arraySlice3d< real64 > const & dPhaseCompFraction_dCompFraction ) const = 0; + +protected: -class FlashModel + /// Array storing the name of the components + arrayView1d< string const > m_componentNames; + + /// Array storing the component molar weights + arrayView1d< real64 const > m_componentMolarWeight; + +}; + + +class FlashModelBase { public: - FlashModel( string const & name, - string_array const & componentNames, - real64_array const & componentMolarWeight ): + FlashModelBase( string const & name, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ): m_modelName( name ), m_componentNames( componentNames ), m_componentMolarWeight( componentMolarWeight ) {} - virtual ~FlashModel(){} + virtual ~FlashModelBase() = default; - using CatalogInterface = dataRepository::CatalogInterface< FlashModel, string_array const &, - string_array const &, - string_array const &, - real64_array const & >; + using CatalogInterface = dataRepository::CatalogInterface< FlashModelBase, array1d< string > const &, + array1d< string > const &, + array1d< string > const &, + array1d< real64 > const & >; static typename CatalogInterface::CatalogType & getCatalog() { static CatalogInterface::CatalogType catalog; return catalog; } + virtual string getCatalogName() const = 0; + string const & flashModelName() const { return m_modelName; } - string const & flashModelName() const - { - return m_modelName; - } +protected: - //partition - //input: P, T, totalCompFraction - //output: phaseFraction, phaseCompFraction + /// Name the solubility model + string m_modelName; - virtual void partition( EvalVarArgs const & pressure, - EvalVarArgs const & temperature, - arraySlice1d< EvalVarArgs const > const & compFraction, - arraySlice1d< EvalVarArgs > const & phaseFraction, - arraySlice2d< EvalVarArgs > const & phaseCompFraction ) const = 0; + /// Array storing the name of the components + array1d< string > m_componentNames; -protected: - string m_modelName; - string_array m_componentNames; - real64_array m_componentMolarWeight; + /// Array storing the component molar weights + array1d< real64 > m_componentMolarWeight; }; -} +} // end namespace PVTProps -} +} // end namespace geosx -#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FLASHMODELBASE_HPP_ +#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWFLASHMODELBASE_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.cpp deleted file mode 100644 index 47e2ddb66f0..00000000000 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * 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 Total, S.A - * Copyright (c) 2019- GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file BrineCO2Density.cpp - */ - -#include "constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.hpp" - -#include "managers/Functions/FunctionManager.hpp" -#include "managers/GeosxState.hpp" - -namespace geosx -{ - -using namespace stringutilities; - -namespace PVTProps -{ - -BrineCO2Density::BrineCO2Density( array1d< string > const & inputPara, - array1d< string > const & componentNames, - array1d< real64 > const & componentMolarWeight ): - PVTFunctionBase( inputPara[1], - componentNames, - componentMolarWeight ) -{ - bool notFound = true; - for( localIndex i = 0; i < componentNames.size(); ++i ) - { - if( componentNames[i] == "CO2" || componentNames[i] == "co2" ) - { - m_CO2Index = i; - notFound = false; - break; - } - } - GEOSX_ERROR_IF( notFound, "Component CO2 is not found!" ); - - notFound = true; - for( localIndex i = 0; i < componentNames.size(); ++i ) - { - if( componentNames[i] == "Water" || componentNames[i] == "water" ) - { - m_waterIndex = i; - notFound = false; - break; - } - } - GEOSX_ERROR_IF( notFound, "Component Water/Brine is not found!" ); - - makeTable( inputPara ); -} - -void BrineCO2Density::makeTable( array1d< string > const & inputPara ) -{ - array1d< array1d< real64 > > coordinates; - coordinates.resize( 2 ); - - real64 TStart = -1.0; - real64 TEnd = -1.0; - real64 dT = -1.0; - real64 PStart = -1.0; - real64 PEnd = -1.0; - real64 dP = -1.0; - real64 salinity = 0.0; - - GEOSX_ERROR_IF( inputPara.size() < 9, "Invalid BrineCO2Density input!" ); - - try - { - PStart = stod( inputPara[2] ); - PEnd = stod( inputPara[3] ); - dP = stod( inputPara[4] ); - - TStart = stod( inputPara[5] ); - TEnd = stod( inputPara[6] ); - dT = stod( inputPara[7] ); - - salinity = stod( inputPara[8] ); - } - catch( const std::invalid_argument & e ) - { - GEOSX_ERROR( "Invalid BrineCO2Density argument:" + string( e.what()) ); - } - - real64 P = PStart; - while( P <= PEnd ) - { - coordinates[0].emplace_back( P ); - P += dP; - } - - real64 T = TStart; - while( T <= TEnd ) - { - coordinates[1].emplace_back( T ); - T += dT; - } - - localIndex const nP = coordinates[0].size(); - localIndex const nT = coordinates[1].size(); - - array1d< real64 > values( nP * nT ); - calculateBrineDensity( coordinates, salinity, values ); - - FunctionManager & functionManager = getGlobalState().getFunctionManager(); - m_brineDensityTable = dynamicCast< TableFunction * >( functionManager.createChild( "TableFunction", "brineDensityTable" ) ); - m_brineDensityTable->setTableCoordinates( coordinates ); - m_brineDensityTable->setTableValues( values ); - m_brineDensityTable->reInitializeFunction(); - m_brineDensityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); -} - -void BrineCO2Density::calculateBrineDensity( array1d< array1d< real64 > > const & coordinates, - real64 const & salinity, - array1d< real64 > const & values ) -{ - // these coefficients come from Phillips et al. (1981), equations (4) and (5), pages 14 and 15 - constexpr real64 c1 = -9.9595; - constexpr real64 c2 = 7.0845; - constexpr real64 c3 = 3.9093; - - constexpr real64 a1 = -0.004539; - constexpr real64 a2 = -0.0001638; - constexpr real64 a3 = 0.00002551; - - constexpr real64 AA = -3.033405; - constexpr real64 BB = 10.128163; - constexpr real64 CC = -8.750567; - constexpr real64 DD = 2.663107; - - localIndex const numPressures = coordinates[0].size(); - localIndex const numTemperatures = coordinates[1].size(); - - for( localIndex i = 0; i < numPressures; ++i ) - { - real64 const P = coordinates[0][i] / 1e5; - - for( localIndex j = 0; j < numTemperatures; ++j ) - { - // see Phillips et al. (1981), equations (4) and (5), pages 14 and 15 - real64 const x = c1 * exp( a1 * salinity ) - + c2 * exp( a2 * coordinates[1][j] ) - + c3 * exp( a3 * P ); - values[j*numPressures+i] = (AA + BB * x + CC * x * x + DD * x * x * x) * 1000.0; - } - } -} - -BrineCO2Density::KernelWrapper BrineCO2Density::createKernelWrapper() -{ - return KernelWrapper( m_componentNames, - m_componentMolarWeight, - m_brineDensityTable, - m_CO2Index, - m_waterIndex ); -} - -REGISTER_CATALOG_ENTRY( PVTFunctionBase, BrineCO2Density, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) - -} // namespace PVTProps - -} // namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.hpp deleted file mode 100644 index 7ba37dc223c..00000000000 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.hpp +++ /dev/null @@ -1,229 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * 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 Total, S.A - * Copyright (c) 2019- GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file BrineCO2Density.hpp - */ - -#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINECO2DENSITY_HPP_ -#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINECO2DENSITY_HPP_ - -#include "NewPVTFunctionBase.hpp" - -#include "managers/Functions/TableFunction.hpp" - -namespace geosx -{ - -namespace PVTProps -{ - -class BrineCO2DensityUpdate final : public PVTFunctionBaseUpdate -{ -public: - - BrineCO2DensityUpdate( arrayView1d< string const > const & componentNames, - arrayView1d< real64 const > const & componentMolarWeight, - TableFunction * brineDensityTable, - localIndex const CO2Index, - localIndex const waterIndex ) - : PVTFunctionBaseUpdate( componentNames, - componentMolarWeight ), - m_brineDensityTable( brineDensityTable->createKernelWrapper() ), - m_CO2Index( CO2Index ), - m_waterIndex( waterIndex ) - {} - - /// Default copy constructor - BrineCO2DensityUpdate( BrineCO2DensityUpdate const & ) = default; - - /// Default move constructor - BrineCO2DensityUpdate( BrineCO2DensityUpdate && ) = default; - - /// Deleted copy assignment operator - BrineCO2DensityUpdate & operator=( BrineCO2DensityUpdate const & ) = delete; - - /// Deleted move assignment operator - BrineCO2DensityUpdate & operator=( BrineCO2DensityUpdate && ) = delete; - - GEOSX_HOST_DEVICE - GEOSX_FORCE_INLINE - virtual void compute( real64 const & pressure, - real64 const & temperature, - arraySlice1d< real64 const > const & phaseComposition, - real64 & value, - real64 & dValue_dPressure, - real64 & dValue_dTemperature, - arraySlice1d< real64 > const & dValue_dPhaseComposition, - bool useMass = 0 ) const override; - -protected: - - /// Table with brine density tabulated as a function (P,T,sal) - TableFunction::KernelWrapper const m_brineDensityTable; - - /// Index of the CO2 component - localIndex const m_CO2Index; - - /// Index of the water component - localIndex const m_waterIndex; - -}; - -class BrineCO2Density : public PVTFunctionBase -{ -public: - - BrineCO2Density( array1d< string > const & inputPara, - array1d< string > const & componentNames, - array1d< real64 > const & componentMolarWeight ); - - ~BrineCO2Density() override {} - - static string catalogName() { return "NewBrineCO2Density"; } - - virtual string getCatalogName() const override final { return catalogName(); } - - virtual PVTFunctionType functionType() const override - { - return PVTFunctionType::DENSITY; - } - - /// Type of kernel wrapper for in-kernel update - using KernelWrapper = BrineCO2DensityUpdate; - - /** - * @brief Create an update kernel wrapper. - * @return the wrapper - */ - KernelWrapper createKernelWrapper(); - - -private: - - void makeTable( array1d< string > const & inputPara ); - - void calculateBrineDensity( array1d< array1d< real64 > > const & coordinates, - real64 const & salinity, - array1d< real64 > const & values ); - - /// Table with brine density tabulated as a function of (P,T,sal) - TableFunction * m_brineDensityTable; - - /// Index of the CO2 phase - localIndex m_CO2Index; - - /// Index of the water phase - localIndex m_waterIndex; - -}; - -GEOSX_HOST_DEVICE -GEOSX_FORCE_INLINE -void BrineCO2DensityUpdate::compute( real64 const & pressure, - real64 const & temperature, - arraySlice1d< real64 const > const & phaseComposition, - real64 & value, - real64 & dValue_dPressure, - real64 & dValue_dTemperature, - arraySlice1d< real64 > const & dValue_dPhaseComposition, - bool useMass ) const -{ - // this method implements the method proposed by E. Garcia (2001) - - // these coefficients come from equation (2) from Garcia (2001) - constexpr real64 a = 37.51; - constexpr real64 b = -9.585e-2; - constexpr real64 c = 8.740e-4; - constexpr real64 d = -5.044e-7; - - real64 const input[2] = { pressure, temperature }; - real64 density = 0.0; - real64 densityDeriv[2]{}; - m_brineDensityTable.compute( input, density, densityDeriv ); - - // equation (2) from Garcia (2001) - real64 const squaredTemp = temperature * temperature; - real64 const V = ( a - + b * temperature - + c * squaredTemp - + d * squaredTemp * temperature ) * 1e-6; - real64 const dV_dTemp = ( b - + 2 * c * temperature - + 3 * d * squaredTemp ) * 1e-6; - - // CO2 concentration - real64 const denom = ( m_componentMolarWeight[m_waterIndex] * ( 1.0 - phaseComposition[m_CO2Index] ) ); - real64 const coef = phaseComposition[m_CO2Index] / denom; - real64 dCoef_dComp[2]{}; - dCoef_dComp[m_CO2Index] = 1.0 / denom; - dCoef_dComp[m_waterIndex] = -m_componentMolarWeight[m_waterIndex] * phaseComposition[m_CO2Index] / (denom * denom); - - real64 const conc = coef * density; - real64 const dConc_dPres = coef * densityDeriv[0]; - real64 const dConc_dTemp = coef * densityDeriv[1]; - real64 dConc_dComp[2]{}; - dConc_dComp[m_CO2Index] = dCoef_dComp[m_CO2Index] * density; - dConc_dComp[m_waterIndex] = dCoef_dComp[m_waterIndex] * density; - - // CO2 concentration times density times vol - real64 const concDensVol = conc * density * V; - real64 const dConcDensVol_dPres = ( dConc_dPres * density + conc * densityDeriv[0] ) * V; - real64 const dConcDensVol_dTemp = ( dConc_dTemp * density + conc * densityDeriv[1] ) * V - + conc * density * dV_dTemp; - real64 dConcDensVol_dComp[2]{}; - dConcDensVol_dComp[m_CO2Index] = dConc_dComp[m_CO2Index] * density * V; - dConcDensVol_dComp[m_waterIndex] = dConc_dComp[m_waterIndex] * density * V; - - // Brine density - // equation (1) from Garcia (2001) - if( useMass ) - { - value = density - + m_componentMolarWeight[m_CO2Index] * conc - - concDensVol; - dValue_dPressure = densityDeriv[0] - + m_componentMolarWeight[m_CO2Index] * dConc_dPres - - dConcDensVol_dPres; - dValue_dTemperature = densityDeriv[1] - + m_componentMolarWeight[m_CO2Index] * dConc_dTemp - - dConcDensVol_dTemp; - dValue_dPhaseComposition[m_CO2Index] = m_componentMolarWeight[m_CO2Index] * dConc_dComp[m_CO2Index] - - dConcDensVol_dComp[m_CO2Index]; - dValue_dPhaseComposition[m_waterIndex] = m_componentMolarWeight[m_CO2Index] * dConc_dComp[m_waterIndex] - - dConcDensVol_dComp[m_waterIndex]; - } - else - { - value = density / m_componentMolarWeight[m_waterIndex] - + conc - - concDensVol / m_componentMolarWeight[m_waterIndex]; - dValue_dPressure = densityDeriv[0] / m_componentMolarWeight[m_waterIndex] - + dConc_dPres - - dConcDensVol_dPres / m_componentMolarWeight[m_waterIndex]; - dValue_dTemperature = densityDeriv[1] / m_componentMolarWeight[m_waterIndex] - + dConc_dTemp - - dConcDensVol_dTemp / m_componentMolarWeight[m_waterIndex]; - dValue_dPhaseComposition[m_CO2Index] = dConc_dComp[m_CO2Index] - - dConcDensVol_dComp[m_CO2Index] / m_componentMolarWeight[m_waterIndex]; - dValue_dPhaseComposition[m_waterIndex] = dConc_dComp[m_waterIndex] - - dConcDensVol_dComp[m_waterIndex] / m_componentMolarWeight[m_waterIndex]; - } -} - -} // end namespace PVTProps - -} // end namespace geosx - -#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINECO2DENSITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.cpp deleted file mode 100644 index 1ebcfe81212..00000000000 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * 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 Total, S.A - * Copyright (c) 2019- GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file BrineViscosity.cpp - */ - -#include "constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.hpp" - -namespace geosx -{ - -using namespace stringutilities; - -namespace PVTProps -{ - -BrineViscosity::BrineViscosity( array1d< string > const & inputPara, - array1d< string > const & componentNames, - array1d< real64 > const & componentMolarWeight ): - PVTFunctionBase( inputPara[1], - componentNames, - componentMolarWeight ) -{ - makeCoefficients( inputPara ); -} - -void BrineViscosity::makeCoefficients( array1d< string > const & inputPara ) -{ - // these coefficients come from Phillips et al. (1981), equation (1), pages 5-6 - constexpr real64 a = 0.0816; - constexpr real64 b = 0.0122; - constexpr real64 c = 0.000128; - constexpr real64 d = 0.000629; - constexpr real64 k = -0.7; - constexpr real64 waterVisc = 8.9e-4; //at 25C - - real64 m = -1.0; - - GEOSX_ERROR_IF( inputPara.size() < 3, "Invalid BrineViscosity input!" ); - - try - { - m = stod( inputPara[2] ); - } - catch( const std::invalid_argument & e ) - { - GEOSX_ERROR( "Invalid BrineViscosity argument:" + string( e.what() ) ); - } - - m_coef0 = (1.0 + a * m + b * m * m + c * m * m * m) * waterVisc; - m_coef1 = d * (1.0 - exp( k * m )) * waterVisc; -} - -BrineViscosity::KernelWrapper BrineViscosity::createKernelWrapper() -{ - return KernelWrapper( m_componentNames, - m_componentMolarWeight, - m_coef0, - m_coef1 ); -} - -REGISTER_CATALOG_ENTRY( PVTFunctionBase, BrineViscosity, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) - -} // end namespace PVTProps - -} // end namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.hpp deleted file mode 100644 index d6b2423e0b4..00000000000 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.hpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * 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 Total, S.A - * Copyright (c) 2019- GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file BrineViscosity.hpp - */ - -#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINEVISCOSITY_HPP_ -#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINEVISCOSITY_HPP_ - -#include "NewPVTFunctionBase.hpp" - -namespace geosx -{ - -namespace PVTProps -{ - -class BrineViscosityUpdate final : public PVTFunctionBaseUpdate -{ -public: - - BrineViscosityUpdate( arrayView1d< string const > const & componentNames, - arrayView1d< real64 const > const & componentMolarWeight, - real64 const & coef0, - real64 const & coef1 ) - : PVTFunctionBaseUpdate( componentNames, - componentMolarWeight ), - m_coef0( coef0 ), - m_coef1( coef1 ) - {} - - /// Default copy constructor - BrineViscosityUpdate( BrineViscosityUpdate const & ) = default; - - /// Default move constructor - BrineViscosityUpdate( BrineViscosityUpdate && ) = default; - - /// Deleted copy assignment operator - BrineViscosityUpdate & operator=( BrineViscosityUpdate const & ) = delete; - - /// Deleted move assignment operator - BrineViscosityUpdate & operator=( BrineViscosityUpdate && ) = delete; - - GEOSX_HOST_DEVICE - GEOSX_FORCE_INLINE - virtual void compute( real64 const & pressure, - real64 const & temperature, - arraySlice1d< real64 const > const & phaseComposition, - real64 & value, - real64 & dValue_dPressure, - real64 & dValue_dTemperature, - arraySlice1d< real64 > const & dValue_dPhaseComposition, - bool useMass = 0 ) const override; - -protected: - - real64 const m_coef0; - - real64 const m_coef1; - -}; - - -class BrineViscosity : public PVTFunctionBase -{ -public: - - BrineViscosity( array1d< string > const & inputPara, - array1d< string > const & componentNames, - array1d< real64 > const & componentMolarWeight ); - - ~BrineViscosity() override {} - - static string catalogName() { return "NewBrineViscosity"; } - - virtual string getCatalogName() const override final { return catalogName(); } - - virtual PVTFunctionType functionType() const override - { - return PVTFunctionType::VISCOSITY; - } - - /// Type of kernel wrapper for in-kernel update - using KernelWrapper = BrineViscosityUpdate; - - /** - * @brief Create an update kernel wrapper. - * @return the wrapper - */ - KernelWrapper createKernelWrapper(); - -private: - - void makeCoefficients( array1d< string > const & inputPara ); - - real64 m_coef0; - - real64 m_coef1; - -}; - -GEOSX_HOST_DEVICE -GEOSX_FORCE_INLINE -void BrineViscosityUpdate::compute( real64 const & pressure, - real64 const & temperature, - arraySlice1d< real64 const > const & phaseComposition, - real64 & value, - real64 & dValue_dPressure, - real64 & dValue_dTemperature, - arraySlice1d< real64 > const & dValue_dPhaseComposition, - bool useMass ) const -{ - GEOSX_UNUSED_VAR( pressure ); - GEOSX_UNUSED_VAR( phaseComposition ); - GEOSX_UNUSED_VAR( useMass ); - - value = m_coef0 + m_coef1 * temperature; - dValue_dPressure = 0.0; - dValue_dTemperature = m_coef1; - for( real64 & val : dValue_dPhaseComposition ) - { - val = 0.0; - } -} - -} // end namespace PVTProps - -} // end namespace geosx - -#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINEVISCOSITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.cpp deleted file mode 100644 index 26ac49dbb96..00000000000 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.cpp +++ /dev/null @@ -1,344 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * 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 Total, S.A - * Copyright (c) 2019- GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file CO2Solubility.cpp - */ - -#include "constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.hpp" - -#include "managers/Functions/FunctionManager.hpp" -#include "managers/GeosxState.hpp" - -namespace geosx -{ - -using namespace stringutilities; - - -namespace PVTProps -{ - -constexpr real64 T_K_f = 273.15; -constexpr real64 P_Pa_f = 1e+5; -constexpr real64 P_c = 73.773 * P_Pa_f; -constexpr real64 T_c = 304.1282; -constexpr real64 Rgas = 8.314467; -constexpr real64 V_c = Rgas*T_c/P_c; - -// these coefficients are in Table (A1) of Duan and Sun (2003) -constexpr real64 acoef[] = -{ 8.99288497e-2, -4.94783127e-1, 4.77922245e-2, 1.03808883e-2, -2.82516861e-2, 9.49887563e-2, 5.20600880e-4, - -2.93540971e-4, -1.77265112e-3, -2.51101973e-5, 8.93353441e-5, 7.88998563e-5, -1.66727022e-2, 1.398, 2.96e-2 }; - -namespace detail -{ - -real64 ff( real64 const & T, real64 const & P, real64 const & V_r ) -{ - // reduced pressure - real64 const P_r = P*P_Pa_f/P_c; - // reduced temperature - real64 const T_r = (T_K_f+T)/T_c; - - // CO2 equation of state - // see equation (A1) in Duan and Sun (2003) - real64 const f_Z = 1.0 - + ( acoef[0] + acoef[1]/(T_r * T_r) + acoef[2]/(T_r * T_r * T_r) )/V_r - + ( acoef[3] + acoef[4]/(T_r * T_r) + acoef[5]/(T_r * T_r * T_r) )/(V_r*V_r) - + ( acoef[6] + acoef[7]/(T_r * T_r) + acoef[8]/(T_r * T_r * T_r) )/(V_r*V_r*V_r*V_r) - + ( acoef[9] + acoef[10]/(T_r * T_r) + acoef[11]/(T_r * T_r * T_r) )/(V_r*V_r*V_r*V_r*V_r) - + acoef[12]/(T_r * T_r * T_r)/(V_r * V_r) * (acoef[13] + acoef[14]/(V_r * V_r)) * exp( -acoef[14]/(V_r * V_r)) - P_r * V_r / T_r; - - return f_Z; -} - -real64 PWater( real64 const & T ) -{ - // these coefficients are defined in Table (B1) of Duan and Sun (2003) - constexpr real64 ccoef[] = { -38.640844, 5.8948420, 59.876516, 26.654627, 10.637097 }; - - // H2O critical pressure (bars) - real64 const P_c_w = 220.85; - // H2O critical temperature (K) - real64 const T_c_w = 647.29; - real64 const tt = ( (T+T_K_f)-T_c_w )/T_c_w; - // Empirical model for water pressure of equation (B1) of Duan and Sun (2003) - real64 const x = (P_c_w*(T+T_K_f)/T_c_w) - * (1 - + ccoef[0]*pow( -tt, 1.9 ) - + ccoef[1]*tt - + ccoef[2]*tt*tt - + ccoef[3]*tt*tt*tt - + ccoef[4]*tt*tt*tt*tt); - - return x; -} - -real64 logF( real64 const & T, real64 const & P, real64 const & V_r ) -{ - // reduced pressure - real64 const P_r = P*P_Pa_f/P_c; - // reduced temperature - real64 const T_r = (T_K_f+T)/T_c; - real64 const Z = P_r * V_r/T_r; - - // fugacity coefficient of CO2, equation (A6) of Duan and Sun (2003) - real64 const log_f = Z - 1 - log( Z ) + - ( acoef[0] + acoef[1]/T_r/T_r + acoef[2]/T_r/T_r/T_r )/V_r - + ( acoef[3] + acoef[4]/T_r/T_r + acoef[5]/T_r/T_r/T_r )/2.0/V_r/V_r - + ( acoef[6] + acoef[7]/T_r/T_r + acoef[8]/T_r/T_r/T_r )/4.0/V_r/V_r/V_r/V_r - + ( acoef[9] + acoef[10]/T_r/T_r + acoef[11]/T_r/T_r/T_r )/5.0/V_r/V_r/V_r/V_r/V_r - + acoef[12]/2.0/T_r/T_r/T_r/acoef[14] * ( acoef[13] + 1.0 - (acoef[13] + 1.0 + acoef[14]/V_r/V_r) * exp( -acoef[14]/V_r/V_r ) ); - - return log_f; -} - -real64 Par( real64 const & T, real64 const & P, real64 const * cc ) -{ - // "equation for the parameters", see equation (7) of Duan and Sun (2003) - real64 x = cc[0] - + cc[1]*T - + cc[2]/T - + cc[3]*T*T - + cc[4]/(630.0-T) - + cc[5]*P - + cc[6]*P *log( T ) - + cc[7]*P/T - + cc[8]*P/(630.0-T) - + cc[9]*P*P/(630.0-T)/(630.0-T) - + cc[10]*T *log( P ); - - return x; -} - -} - -CO2Solubility::CO2Solubility( array1d< string > const & inputPara, - array1d< string > const & phaseNames, - array1d< string > const & componentNames, - array1d< real64 > const & componentMolarWeight ): - FlashModelBase( inputPara[1], - componentNames, - componentMolarWeight ) -{ - GEOSX_ERROR_IF( phaseNames.size() != 2, "The CO2Solubility model is a two-phase model" ); - GEOSX_ERROR_IF( componentNames.size() != 2, "The CO2Solubility model is a two-component model" ); - - bool notFound = true; - for( localIndex i = 0; i < componentNames.size(); ++i ) - { - if( componentNames[i] == "CO2" || componentNames[i] == "co2" ) - { - m_CO2Index = i; - notFound = false; - break; - } - } - GEOSX_ERROR_IF( notFound, "Component CO2 is not found!" ); - - notFound = true; - for( localIndex i = 0; i < componentNames.size(); ++i ) - { - if( componentNames[i] == "Water" || componentNames[i] == "water" ) - { - m_waterIndex = i; - notFound = false; - break; - } - } - GEOSX_ERROR_IF( notFound, "Component Water/Brine is not found!" ); - - notFound = true; - for( localIndex i = 0; i < phaseNames.size(); ++i ) - { - if( phaseNames[i] == "CO2" || phaseNames[i] == "co2" || - phaseNames[i] == "gas" || phaseNames[i] == "Gas" ) - { - m_phaseGasIndex = i; - notFound = false; - break; - } - } - GEOSX_ERROR_IF( notFound, "Phase co2/gas is not found!" ); - - notFound = true; - for( localIndex i = 0; i < phaseNames.size(); ++i ) - { - if( streq( phaseNames[i], "Water" ) || streq( phaseNames[i], "water" ) || - streq( phaseNames[i], "Liquid" ) || streq( phaseNames[i], "liquid" ) ) - { - m_phaseLiquidIndex = i; - notFound = false; - break; - } - } - GEOSX_ERROR_IF( notFound, "Phase water/liquid is not found!" ); - - makeTable( inputPara ); -} - -void CO2Solubility::makeTable( array1d< string > const & inputPara ) -{ - array1d< array1d< real64 > > coordinates; - coordinates.resize( 2 ); - - real64 TStart = -1.0; - real64 TEnd = -1.0; - real64 dT = -1.0; - real64 PStart = -1.0; - real64 PEnd = -1.0; - real64 dP = -1.0; - real64 salinity = 0; - - GEOSX_ERROR_IF( inputPara.size() < 9, "Invalid CO2Solubility input!" ); - - try - { - PStart = stod( inputPara[2] ); - PEnd = stod( inputPara[3] ); - dP = stod( inputPara[4] ); - - TStart = stod( inputPara[5] ); - TEnd = stod( inputPara[6] ); - dT = stod( inputPara[7] ); - - salinity = stod( inputPara[8] ); - } - catch( const std::invalid_argument & e ) - { - GEOSX_ERROR( "Invalid CO2Solubility argument:" + string( e.what()) ); - } - - real64 P = PStart; - while( P <= PEnd ) - { - coordinates[0].emplace_back( P ); - P += dP; - } - - real64 T = TStart; - while( T <= TEnd ) - { - coordinates[1].emplace_back( T ); - T += dT; - } - - localIndex const nP = coordinates[0].size(); - localIndex const nT = coordinates[1].size(); - array1d< real64 > values( nP * nT ); - calculateCO2Solubility( coordinates, salinity, values ); - - FunctionManager & functionManager = getGlobalState().getFunctionManager(); - m_CO2SolubilityTable = dynamicCast< TableFunction * >( functionManager.createChild( "TableFunction", "CO2SolubilityTable" ) ); - m_CO2SolubilityTable->setTableCoordinates( coordinates ); - m_CO2SolubilityTable->setTableValues( values ); - m_CO2SolubilityTable->reInitializeFunction(); - m_CO2SolubilityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); -} - -void CO2Solubility::calculateCO2Solubility( array1d< array1d< real64 > > const & coordinates, - real64 const & salinity, - array1d< real64 > const & values ) -{ - // Interaction parameters, see Table 2 of Duan and Sun (2003) - constexpr real64 mu[] = - { 28.9447706, -0.0354581768, -4770.67077, 1.02782768e-5, 33.8126098, 9.04037140e-3, - -1.14934031e-3, -0.307405726, -0.0907301486, 9.32713393e-4, 0 }; - constexpr real64 lambda[] = { -0.411370585, 6.07632013e-4, 97.5347708, 0, 0, 0, 0, -0.0237622469, 0.0170656236, 0, 1.41335834e-5 }; - constexpr real64 zeta[] = { 3.36389723e-4, -1.98298980e-5, 0, 0, 0, 0, 0, 2.12220830e-3, -5.24873303e-3, 0, 0 }; - - localIndex const numPressures = coordinates[0].size(); - localIndex const numTemperatures = coordinates[1].size(); - - for( localIndex i = 0; i < numPressures; ++i ) - { - real64 const P = coordinates[0][i] / P_Pa_f; - - for( localIndex j = 0; j < numTemperatures; ++j ) - { - real64 const T = coordinates[1][j]; - - // compute reduced volume by solving the CO2 equation of state - real64 V_r = 0.0; - CO2SolubilityFunction( T, P, V_r, &detail::ff ); - - // compute equation (6) of Duan and Sun (2003) - real64 const logK = detail::Par( T+T_K_f, P, mu ) - - detail::logF( T, P, V_r ) - + 2*detail::Par( T+T_K_f, P, lambda ) * salinity - + detail::Par( T+T_K_f, P, zeta ) * salinity * salinity; - - // mole fraction of CO2 in vapor phase, equation (4) of Duan and Sun (2003) - real64 const y_CO2 = (P - detail::PWater( T ))/P; - values[j*numPressures+i] = y_CO2 * P / exp( logK ); - } - } -} - -void CO2Solubility::CO2SolubilityFunction( real64 const & T, - real64 const & P, - real64 & V_r, - real64 (*f)( real64 const & x1, real64 const & x2, real64 const & x3 ) ) -{ - - constexpr real64 eps = 1e-9; - constexpr real64 dx = 1e-10; - int count = 0; - real64 Vr_int = 0.05; - - V_r = 0.75*Rgas*(T_K_f+T)/(P*P_Pa_f)*(1/V_c); - - // iterate until the solution of the CO2 equation of state is found - for(;; ) - { - if( V_r < 0.0 ) - { - V_r = Vr_int; - Vr_int += 0.05; - } - - real64 const v0 = (*f)( T, P, V_r ); - real64 const v1 = (*f)( T, P, V_r+dx ); - real64 const dre = -v0/((v1-v0)/dx); - - if( fabs( dre ) < eps ) - { - break; - } - - GEOSX_ERROR_IF( count > 50, "CO2Solubility NR convergence fails! " << "dre = " << dre << ", eps = " << eps ); - - count++; - V_r += dre; - } -} - - -CO2Solubility::KernelWrapper CO2Solubility::createKernelWrapper() -{ - return KernelWrapper( m_componentNames, - m_componentMolarWeight, - m_CO2SolubilityTable, - m_CO2Index, - m_waterIndex, - m_phaseGasIndex, - m_phaseLiquidIndex ); -} - -REGISTER_CATALOG_ENTRY( FlashModelBase, CO2Solubility, array1d< string > const &, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) - -} // end namespace PVTProps - -} // end namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.hpp deleted file mode 100644 index 8a912bc69d4..00000000000 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.hpp +++ /dev/null @@ -1,298 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * 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 Total, S.A - * Copyright (c) 2019- GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file CO2Solubility.hpp - */ - -#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_CO2SOLUBILITY_HPP_ -#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_CO2SOLUBILITY_HPP_ - -#include "NewFlashModelBase.hpp" - -#include "managers/Functions/TableFunction.hpp" - -namespace geosx -{ - -namespace PVTProps -{ - -constexpr real64 minForDivision = 1e-10; - -class CO2SolubilityUpdate final : public FlashModelBaseUpdate -{ -public: - - CO2SolubilityUpdate( arrayView1d< string const > const & componentNames, - arrayView1d< real64 const > const & componentMolarWeight, - TableFunction * CO2SolubilityTable, - localIndex const CO2Index, - localIndex const waterIndex, - localIndex const phaseGasIndex, - localIndex const phaseLiquidIndex ) - : FlashModelBaseUpdate( componentNames, - componentMolarWeight ), - m_CO2SolubilityTable( CO2SolubilityTable->createKernelWrapper() ), - m_CO2Index( CO2Index ), - m_waterIndex( waterIndex ), - m_phaseGasIndex( phaseGasIndex ), - m_phaseLiquidIndex( phaseLiquidIndex ) - {} - - /// Default copy constructor - CO2SolubilityUpdate( CO2SolubilityUpdate const & ) = default; - - /// Default move constructor - CO2SolubilityUpdate( CO2SolubilityUpdate && ) = default; - - /// Deleted copy assignment operator - CO2SolubilityUpdate & operator=( CO2SolubilityUpdate const & ) = delete; - - /// Deleted move assignment operator - CO2SolubilityUpdate & operator=( CO2SolubilityUpdate && ) = delete; - - GEOSX_HOST_DEVICE - GEOSX_FORCE_INLINE - virtual void compute( real64 const & pressure, - real64 const & temperature, - arraySlice1d< real64 const > const & compFraction, - arraySlice1d< real64 > const & phaseFraction, - arraySlice1d< real64 > const & dPhaseFraction_dPressure, - arraySlice1d< real64 > const & dPhaseFraction_dTemperature, - arraySlice2d< real64 > const & dPhaseFraction_dCompFraction, - arraySlice2d< real64 > const & phaseCompFraction, - arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, - arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, - arraySlice3d< real64 > const & dPhaseCompFraction_dCompFraction ) const; - -protected: - - /// Table with CO2 solubility tabulated as a function (P,T) - TableFunction::KernelWrapper const m_CO2SolubilityTable; - - /// Index of the CO2 phase - localIndex const m_CO2Index; - - /// Index of the water phase - localIndex const m_waterIndex; - - /// Index of the gas phase - localIndex const m_phaseGasIndex; - - /// Index of the liquid phase - localIndex const m_phaseLiquidIndex; - -}; - -class CO2Solubility : public FlashModelBase -{ -public: - - CO2Solubility( array1d< string > const & inputPara, - array1d< string > const & phaseNames, - array1d< string > const & componentNames, - array1d< real64 > const & componentMolarWeight ); - - ~CO2Solubility() override {} - - static string catalogName() { return "NewCO2Solubility"; } - - virtual string getCatalogName() const override final { return catalogName(); } - - /// Type of kernel wrapper for in-kernel update - using KernelWrapper = CO2SolubilityUpdate; - - /** - * @brief Create an update kernel wrapper. - * @return the wrapper - */ - KernelWrapper createKernelWrapper(); - -private: - - void makeTable( array1d< string > const & inputPara ); - - void calculateCO2Solubility( array1d< array1d< real64 > > const & coordinates, - real64 const & salinity, - array1d< real64 > const & values ); - - void CO2SolubilityFunction( real64 const & T, - real64 const & P, - real64 & V_r, - real64 (*f)( real64 const & x1, real64 const & x2, real64 const & x3 ) ); - - /// Table to compute solubility as a function of pressure and temperature - TableFunction * m_CO2SolubilityTable; - - /// Index of the CO2 component - localIndex m_CO2Index; - - /// Index of the water component - localIndex m_waterIndex; - - /// Index of the gas phase - localIndex m_phaseGasIndex; - - /// Index of the liquid phase - localIndex m_phaseLiquidIndex; -}; - -GEOSX_HOST_DEVICE -GEOSX_FORCE_INLINE -void CO2SolubilityUpdate::compute( real64 const & pressure, - real64 const & temperature, - arraySlice1d< real64 const > const & compFraction, - arraySlice1d< real64 > const & phaseFraction, - arraySlice1d< real64 > const & dPhaseFraction_dPressure, - arraySlice1d< real64 > const & dPhaseFraction_dTemperature, - arraySlice2d< real64 > const & dPhaseFraction_dCompFraction, - arraySlice2d< real64 > const & phaseCompFraction, - arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, - arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, - arraySlice3d< real64 > const & dPhaseCompFraction_dCompFraction ) const -{ - // solubility mol/kg(water) X = Csat/W - real64 const input[2] = { pressure, temperature }; - real64 solubility = 0.0; - real64 solubilityDeriv[2]{}; - m_CO2SolubilityTable.compute( input, solubility, solubilityDeriv ); - - solubility *= m_componentMolarWeight[m_waterIndex]; - for( localIndex i = 0; i < 2; ++i ) - { - solubilityDeriv[i] *= m_componentMolarWeight[m_waterIndex]; - } - - real64 Y = 0.0; - real64 dY_dCompFrac[2]{}; - - // Y = C/W = z/(1-z) - - if( compFraction[m_CO2Index] > 1.0 - minForDivision ) - { - Y = compFraction[m_CO2Index] / minForDivision; - dY_dCompFrac[m_CO2Index] = (1.0 - compFraction[m_CO2Index]) / minForDivision; - dY_dCompFrac[m_waterIndex] = -compFraction[m_CO2Index] / minForDivision; - } - else - { - real64 const oneMinusCompFracInv = 1.0 / (1.0 - compFraction[m_CO2Index]); - Y = compFraction[m_CO2Index] * oneMinusCompFracInv; - dY_dCompFrac[m_CO2Index] = 1.0 * oneMinusCompFracInv; - dY_dCompFrac[m_waterIndex] = -compFraction[m_CO2Index] * oneMinusCompFracInv * oneMinusCompFracInv; - } - - if( Y < solubility ) - { - // liquid phase only - - // 1) Compute phase fractions - - phaseFraction[m_phaseLiquidIndex] = 1.0; - phaseFraction[m_phaseGasIndex] = 0.0; - for( real64 & val : dPhaseFraction_dPressure ) - { - val = 0.0; - } - for( real64 & val : dPhaseFraction_dTemperature ) - { - val = 0.0; - } - for( real64 & val : dPhaseFraction_dCompFraction ) - { - val = 0.0; - } - - // 2) Compute phase component fractions - - for( localIndex ic = 0; ic < 2; ++ic ) - { - phaseCompFraction[m_phaseLiquidIndex][ic] = compFraction[ic]; - // the two following lines are not present in Yue's code, unclear if this will have some consequences - phaseCompFraction[m_phaseGasIndex][m_CO2Index] = 1.0; - phaseCompFraction[m_phaseGasIndex][m_waterIndex] = 0.0; - for( localIndex jc = 0; jc < 2; ++jc ) - { - dPhaseCompFraction_dCompFraction[m_phaseLiquidIndex][ic][jc] = - (ic == jc ) ? ( 1 - compFraction[ic] ) : -compFraction[ic]; - dPhaseCompFraction_dCompFraction[m_phaseGasIndex][ic][jc] = 0.0; - } - } - for( real64 & val : dPhaseCompFraction_dPressure ) - { - val = 0.0; - } - for( real64 & val : dPhaseCompFraction_dTemperature ) - { - val = 0.0; - } - - } - else - { - // two-phase flow - - // 1) Compute phase fractions - - // liquid phase fraction = (Csat + W) / (C + W) = (Csat/W + 1) / (C/W + 1) - real64 const onePlusYInv = 1.0 / ( 1.0 + Y ); - phaseFraction[m_phaseLiquidIndex] = (solubility + 1.0) * onePlusYInv; - dPhaseFraction_dPressure[m_phaseLiquidIndex] = solubilityDeriv[0] * onePlusYInv; - dPhaseFraction_dTemperature[m_phaseLiquidIndex] = solubilityDeriv[1] * onePlusYInv; - dPhaseFraction_dCompFraction[m_phaseLiquidIndex][m_CO2Index] = - -dY_dCompFrac[m_CO2Index] * phaseFraction[m_phaseLiquidIndex] * onePlusYInv; - dPhaseFraction_dCompFraction[m_phaseLiquidIndex][m_waterIndex] = - -dY_dCompFrac[m_waterIndex] * phaseFraction[m_phaseLiquidIndex] * onePlusYInv; - - phaseFraction[m_phaseGasIndex] = 1.0 - phaseFraction[m_phaseLiquidIndex]; - dPhaseFraction_dPressure[m_phaseGasIndex] = -dPhaseFraction_dPressure[m_phaseLiquidIndex]; - dPhaseFraction_dTemperature[m_phaseGasIndex] = -dPhaseFraction_dTemperature[m_phaseLiquidIndex]; - dPhaseFraction_dCompFraction[m_phaseGasIndex][m_CO2Index] = -dPhaseFraction_dCompFraction[m_phaseLiquidIndex][m_CO2Index]; - dPhaseFraction_dCompFraction[m_phaseGasIndex][m_waterIndex] = -dPhaseFraction_dCompFraction[m_phaseLiquidIndex][m_waterIndex]; - - // 2) Compute phase component fractions - - // liquid phase composition CO2 = Csat / (Csat + W) = (Csat/W) / (Csat/W + 1) - real64 const onePlusSolubilityInv = 1.0 / ( 1.0 + solubility ); - phaseCompFraction[m_phaseLiquidIndex][m_CO2Index] = solubility * onePlusSolubilityInv; - dPhaseCompFraction_dPressure[m_phaseLiquidIndex][m_CO2Index] = solubilityDeriv[0] * (onePlusSolubilityInv*onePlusSolubilityInv); - dPhaseCompFraction_dTemperature[m_phaseLiquidIndex][m_CO2Index] = solubilityDeriv[1] * (onePlusSolubilityInv*onePlusSolubilityInv); - - phaseCompFraction[m_phaseLiquidIndex][m_waterIndex] = 1.0 - phaseCompFraction[m_phaseLiquidIndex][m_CO2Index]; - dPhaseCompFraction_dPressure[m_phaseLiquidIndex][m_waterIndex] = -dPhaseCompFraction_dPressure[m_phaseLiquidIndex][m_CO2Index]; - dPhaseCompFraction_dTemperature[m_phaseLiquidIndex][m_waterIndex] = -dPhaseCompFraction_dTemperature[m_phaseLiquidIndex][m_CO2Index]; - - // gas phase composition CO2 = 1.0 - - phaseCompFraction[m_phaseGasIndex][m_CO2Index] = 1.0; - phaseCompFraction[m_phaseGasIndex][m_waterIndex] = 0.0; - dPhaseCompFraction_dPressure[m_phaseGasIndex][m_CO2Index] = 0.0; - dPhaseCompFraction_dPressure[m_phaseGasIndex][m_waterIndex] = 0.0; - dPhaseCompFraction_dTemperature[m_phaseGasIndex][m_CO2Index] = 0.0; - dPhaseCompFraction_dTemperature[m_phaseGasIndex][m_waterIndex] = 0.0; - - // phaseCompFraction does not depend on globalComponentFraction - for( real64 & val : dPhaseCompFraction_dCompFraction ) - { - val = 0.0; - } - } -} - -} // end namespace PVTProps - -} // end namespace geosx - -#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_CO2SOLUBILITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.cpp deleted file mode 100644 index d0333be5ba1..00000000000 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * 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 Total, S.A - * Copyright (c) 2019- GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file FenghourCO2Viscosity.cpp - */ - -#include "constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.hpp" - -#include "constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.hpp" -#include "managers/Functions/FunctionManager.hpp" -#include "managers/GeosxState.hpp" - -namespace geosx -{ - -namespace PVTProps -{ - -FenghourCO2Viscosity::FenghourCO2Viscosity( array1d< string > const & inputPara, - array1d< string > const & componentNames, - array1d< real64 > const & componentMolarWeight ): - PVTFunctionBase( inputPara[1], - componentNames, - componentMolarWeight ) -{ - makeTable( inputPara ); -} - -void FenghourCO2Viscosity::makeTable( array1d< string > const & inputPara ) -{ - array1d< array1d< real64 > > coordinates; - coordinates.resize( 2 ); - - real64 TStart = -1.0; - real64 TEnd = -1.0; - real64 dT = -1.0; - real64 PStart = -1.0; - real64 PEnd = -1.0; - real64 dP = -1.0; - - GEOSX_ERROR_IF( inputPara.size() < 8, "Invalid FenghourCO2Viscosity input!" ); - - try - { - PStart = stod( inputPara[2] ); - PEnd = stod( inputPara[3] ); - dP = stod( inputPara[4] ); - - TStart = stod( inputPara[5] ); - TEnd = stod( inputPara[6] ); - dT = stod( inputPara[7] ); - } - catch( const std::invalid_argument & e ) - { - GEOSX_ERROR( "Invalid FenghourCO2Viscosity argument:" + string( e.what()) ); - } - - real64 P = PStart; - while( P <= PEnd ) - { - coordinates[0].emplace_back( P ); - P += dP; - } - - real64 T = TStart; - while( T <= TEnd ) - { - coordinates[1].emplace_back( T ); - T += dT; - } - - localIndex nP = coordinates[0].size(); - localIndex nT = coordinates[1].size(); - array1d< real64 > valuesDensity( nP * nT ); - array1d< real64 > valuesViscosity( nP * nT ); - SpanWagnerCO2Density::calculateCO2Density( coordinates, valuesDensity ); - calculateCO2Viscosity( coordinates, valuesDensity, valuesViscosity ); - - FunctionManager & functionManager = getGlobalState().getFunctionManager(); - m_CO2ViscosityTable = dynamicCast< TableFunction * >( functionManager.createChild( "TableFunction", "CO2ViscosityTable" ) ); - m_CO2ViscosityTable->setTableCoordinates( coordinates ); - m_CO2ViscosityTable->setTableValues( valuesViscosity ); - m_CO2ViscosityTable->reInitializeFunction(); - m_CO2ViscosityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); -} - -void FenghourCO2Viscosity::fenghourCO2ViscosityFunction( real64 const & temperatureCent, - real64 const & density, - real64 & viscosity ) -{ - constexpr real64 espar = 251.196; - constexpr real64 esparInv = 1.0 / espar; - // coefficients from Table (1) of Fenghour and Wakeham (1998) - constexpr real64 aa[5] = { 0.235156, -0.491266, 5.211155e-2, 5.347906e-2, -1.537102e-2 }; - // coefficients from Table (3) of Fenghour and Wakeham (1998) - constexpr real64 d11 = 0.4071119e-2; - constexpr real64 d21 = 0.7198037e-4; - constexpr real64 d64 = 0.2411697e-16; - constexpr real64 d81 = 0.2971072e-22; - constexpr real64 d82 = -0.1627888e-22; - // we neglect critical viscosity - constexpr real64 vcrit = 0.0; - - // temperature in Kelvin - real64 const temperatureKelvin = temperatureCent + 273.15; - // equation (5) of Fenghour and Wakeham (1998) - real64 const Tred = temperatureKelvin * esparInv; - real64 const x = log( Tred ); - // equation (4) of Fenghour and Wakeham (1998) - real64 const lnGfun = aa[0] + x * (aa[1] + x * (aa[2] + x *(aa[3] + x * aa[4]))); - real64 const GfunInv = exp( -lnGfun ); - // equation (3) of Fenghour and Wakeham (1998) - real64 const vlimit = 1.00697 * sqrt( temperatureKelvin ) * GfunInv; - - // equation (8) of Fenghour and Wakeham (1998) - real64 const d2 = density * density; - real64 const vxcess = density * (d11 + density * (d21 + d2*d2*(d64 / (Tred*Tred*Tred) + d2*(d81 + d82/Tred)))); - - // equation (1) of Fenghour and Wakeham (1998) - viscosity = 1e-6 * (vlimit + vxcess + vcrit); -} - -void FenghourCO2Viscosity::calculateCO2Viscosity( array1d< array1d< real64 > > const & coordinates, - array1d< real64 > const & valuesDensity, - array1d< real64 > const & valuesViscosity ) -{ - localIndex const numPressures = coordinates[0].size(); - localIndex const numTemperatures = coordinates[1].size(); - - for( localIndex i = 0; i < numPressures; ++i ) - { - for( localIndex j = 0; j < numTemperatures; ++j ) - { - fenghourCO2ViscosityFunction( coordinates[1][j], - valuesDensity[j*numPressures+i], - valuesViscosity[j*numPressures+i] ); - } - } -} - -FenghourCO2Viscosity::KernelWrapper FenghourCO2Viscosity::createKernelWrapper() -{ - return KernelWrapper( m_componentNames, - m_componentMolarWeight, - m_CO2ViscosityTable ); -} - -REGISTER_CATALOG_ENTRY( PVTFunctionBase, FenghourCO2Viscosity, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) - -} // end namespace PVTProps - -} // end namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.hpp deleted file mode 100644 index e6d1dc0da6f..00000000000 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.hpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * 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 Total, S.A - * Copyright (c) 2019- GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file FenghourCO2Viscosity.hpp - */ - -#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FENGHOURCO2VISCOSITY_HPP_ -#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FENGHOURCO2VISCOSITY_HPP_ - -#include "NewPVTFunctionBase.hpp" - -#include "managers/Functions/TableFunction.hpp" - -namespace geosx -{ - -namespace PVTProps -{ - -class FenghourCO2ViscosityUpdate final : public PVTFunctionBaseUpdate -{ -public: - - FenghourCO2ViscosityUpdate( arrayView1d< string const > const & componentNames, - arrayView1d< real64 const > const & componentMolarWeight, - TableFunction * CO2ViscosityTable ) - : PVTFunctionBaseUpdate( componentNames, - componentMolarWeight ), - m_CO2ViscosityTable( CO2ViscosityTable->createKernelWrapper() ) - {} - - /// Default copy constructor - FenghourCO2ViscosityUpdate( FenghourCO2ViscosityUpdate const & ) = default; - - /// Default move constructor - FenghourCO2ViscosityUpdate( FenghourCO2ViscosityUpdate && ) = default; - - /// Deleted copy assignment operator - FenghourCO2ViscosityUpdate & operator=( FenghourCO2ViscosityUpdate const & ) = delete; - - /// Deleted move assignment operator - FenghourCO2ViscosityUpdate & operator=( FenghourCO2ViscosityUpdate && ) = delete; - - GEOSX_HOST_DEVICE - GEOSX_FORCE_INLINE - virtual void compute( real64 const & pressure, - real64 const & temperature, - arraySlice1d< real64 const > const & phaseComposition, - real64 & value, - real64 & dValue_dPressure, - real64 & dValue_dTemperature, - arraySlice1d< real64 > const & dValue_dPhaseComposition, - bool useMass = 0 ) const override; - -protected: - - /// Table with viscosity tabulated as a function (P,T) - TableFunction::KernelWrapper const m_CO2ViscosityTable; - -}; - -class FenghourCO2Viscosity : public PVTFunctionBase -{ -public: - - FenghourCO2Viscosity( array1d< string > const & inputPara, - array1d< string > const & componentNames, - array1d< real64 > const & componentMolarWeight ); - ~FenghourCO2Viscosity() override {} - - static string catalogName() { return "NewFenghourCO2Viscosity"; } - - virtual string getCatalogName() const override final { return catalogName(); } - - virtual PVTFunctionType functionType() const override - { - return PVTFunctionType::VISCOSITY; - } - - /// Type of kernel wrapper for in-kernel update - using KernelWrapper = FenghourCO2ViscosityUpdate; - - /** - * @brief Create an update kernel wrapper. - * @return the wrapper - */ - KernelWrapper createKernelWrapper(); - -private: - - void makeTable( array1d< string > const & inputPara ); - - void calculateCO2Viscosity( array1d< array1d< real64 > > const & coordinates, - array1d< real64 > const & valuesDensity, - array1d< real64 > const & valuesViscosity ); - - void fenghourCO2ViscosityFunction( real64 const & temperatureCent, - real64 const & density, - real64 & viscosity ); - - /// Table with CO2 viscosity tabulated as a function of (P,T) - TableFunction * m_CO2ViscosityTable; - -}; - -GEOSX_HOST_DEVICE -GEOSX_FORCE_INLINE -void FenghourCO2ViscosityUpdate::compute( real64 const & pressure, - real64 const & temperature, - arraySlice1d< real64 const > const & phaseComposition, - real64 & value, - real64 & dValue_dPressure, - real64 & dValue_dTemperature, - arraySlice1d< real64 > const & dValue_dPhaseComposition, - bool useMass ) const -{ - GEOSX_UNUSED_VAR( phaseComposition ); - GEOSX_UNUSED_VAR( useMass ); - - real64 const input[2] = { pressure, temperature }; - real64 densityDeriv[2]{}; - m_CO2ViscosityTable.compute( input, value, densityDeriv ); - dValue_dPressure = densityDeriv[0]; - dValue_dTemperature = densityDeriv[1]; - - for( real64 & val : dValue_dPhaseComposition ) - { - val = 0.0; - } -} - -} // end namespace PVTProps - -} // end namespace geosx - -#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FENGHOURCO2VISCOSITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewFlashModelBase.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewFlashModelBase.hpp deleted file mode 100644 index 41365b7d136..00000000000 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/NewFlashModelBase.hpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * 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 Total, S.A - * Copyright (c) 2019- GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file FlashModelBase.hpp - */ - -#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWFLASHMODELBASE_HPP_ -#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWFLASHMODELBASE_HPP_ - -#include "codingUtilities/StringUtilities.hpp" -#include "dataRepository/ObjectCatalog.hpp" - -namespace geosx -{ - -namespace PVTProps -{ - -class FlashModelBaseUpdate -{ -public: - - FlashModelBaseUpdate( arrayView1d< string const > const & componentNames, - arrayView1d< real64 const > const & componentMolarWeight ) - : - m_componentNames( componentNames ), - m_componentMolarWeight( componentMolarWeight ) - {} - - /// Default copy constructor - FlashModelBaseUpdate( FlashModelBaseUpdate const & ) = default; - - /// Default move constructor - FlashModelBaseUpdate( FlashModelBaseUpdate && ) = default; - - /// Deleted copy assignment operator - FlashModelBaseUpdate & operator=( FlashModelBaseUpdate const & ) = delete; - - /// Deleted move assignment operator - FlashModelBaseUpdate & operator=( FlashModelBaseUpdate && ) = delete; - - GEOSX_HOST_DEVICE - GEOSX_FORCE_INLINE - virtual void compute( real64 const & pressure, - real64 const & temperature, - arraySlice1d< real64 const > const & compFraction, - arraySlice1d< real64 > const & phaseFraction, - arraySlice1d< real64 > const & dPhaseFraction_dPressure, - arraySlice1d< real64 > const & dPhaseFraction_dTemperature, - arraySlice2d< real64 > const & dPhaseFraction_dCompFraction, - arraySlice2d< real64 > const & phaseCompFraction, - arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, - arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, - arraySlice3d< real64 > const & dPhaseCompFraction_dCompFraction ) const = 0; - -protected: - - /// Array storing the name of the components - arrayView1d< string const > m_componentNames; - - /// Array storing the component molar weights - arrayView1d< real64 const > m_componentMolarWeight; - -}; - - -class FlashModelBase -{ -public: - - FlashModelBase( string const & name, - array1d< string > const & componentNames, - array1d< real64 > const & componentMolarWeight ): - m_modelName( name ), - m_componentNames( componentNames ), - m_componentMolarWeight( componentMolarWeight ) - {} - - virtual ~FlashModelBase() = default; - - using CatalogInterface = dataRepository::CatalogInterface< FlashModelBase, array1d< string > const &, - array1d< string > const &, - array1d< string > const &, - array1d< real64 > const & >; - static typename CatalogInterface::CatalogType & getCatalog() - { - static CatalogInterface::CatalogType catalog; - return catalog; - } - - virtual string getCatalogName() const = 0; - - string const & flashModelName() const { return m_modelName; } - -protected: - - /// Name the solubility model - string m_modelName; - - /// Array storing the name of the components - array1d< string > m_componentNames; - - /// Array storing the component molar weights - array1d< real64 > m_componentMolarWeight; - -}; - -} // end namespace PVTProps - -} // end namespace geosx - -#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWFLASHMODELBASE_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewPVTFunctionBase.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewPVTFunctionBase.hpp deleted file mode 100644 index 8635699dc81..00000000000 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/NewPVTFunctionBase.hpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * 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 Total, S.A - * Copyright (c) 2019- GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file NewPVTFunctionBase.hpp - */ - -#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWPVTFUNCTIONBASE_HPP_ -#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWPVTFUNCTIONBASE_HPP_ - -#include "codingUtilities/StringUtilities.hpp" -#include "dataRepository/ObjectCatalog.hpp" - -namespace geosx -{ - -namespace PVTProps -{ - -enum class PVTFunctionType { UNKNOWN, DENSITY, VISCOSITY }; - -class PVTFunctionBaseUpdate -{ -public: - PVTFunctionBaseUpdate( arrayView1d< string const > const & componentNames, - arrayView1d< real64 const > const & componentMolarWeight ) - : - m_componentNames( componentNames ), - m_componentMolarWeight( componentMolarWeight ) - {} - - /// Default copy constructor - PVTFunctionBaseUpdate( PVTFunctionBaseUpdate const & ) = default; - - /// Default move constructor - PVTFunctionBaseUpdate( PVTFunctionBaseUpdate && ) = default; - - /// Deleted copy assignment operator - PVTFunctionBaseUpdate & operator=( PVTFunctionBaseUpdate const & ) = delete; - - /// Deleted move assignment operator - PVTFunctionBaseUpdate & operator=( PVTFunctionBaseUpdate && ) = delete; - - GEOSX_HOST_DEVICE - GEOSX_FORCE_INLINE - virtual void compute( real64 const & pressure, - real64 const & temperature, - arraySlice1d< real64 const > const & phaseComposition, - real64 & value, - real64 & dValue_dPresure, - real64 & dValue_dTemperature, - arraySlice1d< real64 > const & dValue_dPhaseComposition, - bool useMass = 0 ) const = 0; - -protected: - - /// Array storing the name of the components - arrayView1d< string const > m_componentNames; - - /// Array storing the component molar weights - arrayView1d< real64 const > m_componentMolarWeight; - -}; - -class PVTFunctionBase -{ - -public: - - PVTFunctionBase( string const & name, - array1d< string > const & componentNames, - array1d< real64 > const & componentMolarWeight ) - : - m_functionName( name ), - m_componentNames( componentNames ), - m_componentMolarWeight( componentMolarWeight ) - {} - - virtual ~PVTFunctionBase() = default; - - using CatalogInterface = dataRepository::CatalogInterface< PVTFunctionBase, array1d< string > const &, - array1d< string > const &, - array1d< real64 > const & >; - static typename CatalogInterface::CatalogType & getCatalog() - { - static CatalogInterface::CatalogType catalog; - return catalog; - } - - virtual string getCatalogName() const = 0; - - string const & functionName() const { return m_functionName; } - - virtual PVTFunctionType functionType() const = 0; - -protected: - - /// Name of the PVT function - string m_functionName; - - /// Array storing the name of the components - array1d< string > m_componentNames; - - /// Array storing the component molar weights - array1d< real64 > m_componentMolarWeight; - -}; - -} // end namespace PVTProps - -} // end namespace geosx - -#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWPVTFUNCTIONBASE_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.cpp deleted file mode 100644 index 846e7f215f8..00000000000 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.cpp +++ /dev/null @@ -1,321 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * 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 Total, S.A - * Copyright (c) 2019- GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file SpanWagnerCO2Density.cpp - */ - -#include "constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.hpp" - -#include "managers/Functions/FunctionManager.hpp" -#include "managers/GeosxState.hpp" - -namespace geosx -{ - -using namespace stringutilities; - -namespace PVTProps -{ - -namespace detail -{ - -real64 f( real64 const & T, - real64 const & P, - real64 const & rho ) -{ - // all the coefficients below are defined in Table (31) of Span and Wagner (1996) - // the variable names used below follow the notation of the Table - constexpr real64 n[] = - {0.38856823203161, 2.938547594274, -5.5867188534934, -0.76753199592477, 0.31729005580416, 0.54803315897767, 0.12279411220335, 2.165896154322, - 1.5841735109724, -0.23132705405503, 0.058116916431436, -0.55369137205382, 0.48946615909422, -0.024275739843501, 0.062494790501678, -0.12175860225246, - -0.37055685270086, -0.016775879700426, -0.11960736637987, -0.045619362508778, 0.035612789270346, -0.0074427727132052, -0.0017395704902432, - -0.021810121289527, 0.024332166559236, -0.037440133423463, 0.14338715756878, -0.13491969083286, -0.02315122505348, 0.012363125492901, 0.002105832197294, - -0.00033958519026368, 0.0055993651771592, -0.00030335118055646, -213.65488688320, 26641.569149272, -24027.212204557, -283.41603423999, 212.47284400179, - -0.66642276540751, 0.72608632349897, 0.055068668612842}; - - constexpr real64 d[] = {1, 1, 1, 1, 2, 2, 3, 1, 2, 4, 5, 5, 5, 6, 6, 6, 1, 1, 4, 4, 4, 7, 8, 2, 3, 3, 5, 5, 6, 7, 8, 10, 4, 8, 2, 2, 2, 3, 3}; - - constexpr real64 t[] = - {0, 0.75, 1, 2, 0.75, 2, 0.75, 1.5, 1.5, 2.5, 0, 1.5, 2, 0, 1, 2, 3, 6, 3, 6, 8, 6, 0, 7, 12, 16, 22, 24, 16, 24, 8, 2, 28, 14, 1, 0, 1, 3, 3}; - - constexpr real64 c[] = {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 6}; - - constexpr real64 alpha[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 15, 20}; - - constexpr real64 beta[] = - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 300, 300, 275, 275, 0.3, 0.3, 0.3}; - - constexpr real64 gamma0[] = - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.16, 1.19, 1.19, 1.25, 1.22}; - - constexpr real64 epslon[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1., 1., 1., 1., 1.}; - - constexpr real64 a[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.5, 3.5, 3.}; - - constexpr real64 b[] = - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.875, 0.925, 0.875}; - - constexpr real64 A[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.7, 0.7, 0.7}; - - constexpr real64 B[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.3, 0.3, 1.0}; - - constexpr real64 C[] = - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10.0, 10.0, 12.5}; - - constexpr real64 D[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 275, 275}; - - constexpr real64 T_c = 304.1282; - constexpr real64 rho_c = 467.6; - - constexpr real64 R = 188.9241; - - real64 const tau = T_c / T; - real64 const delta = rho / rho_c; - - real64 theta, Delta, Phi, dPhi_delta, dDelta_delta, dDelta_delta_b; - - // residual part of the energy equation - // this is defined in Table (32) of Span and Wagner (1996) - real64 phi_r_delta = 0.0; - - for( int i=0; i<7; i++ ) - { - phi_r_delta += n[i] * d[i] * pow( delta, d[i]-1.0 ) * pow( tau, t[i] ); - } - - for( int i=7; i<34; i++ ) - { - phi_r_delta += n[i] * exp( -pow( delta, c[i] )) * pow( delta, d[i] - 1.0 ) * pow( tau, t[i] ) * (d[i] - c[i] * pow( delta, c[i] )); - } - - for( int i=34; i<39; i++ ) - { - phi_r_delta += n[i] * - pow( delta, - d[i] ) * - pow( tau, - t[i] ) * - exp( -alpha[i] * - pow( delta - epslon[i], 2.0 ) - beta[i] * pow( tau - gamma0[i], 2.0 )) * (d[i] / delta - 2.0 * alpha[i] * (delta - epslon[i])); - } - - for( int i=39; i<42; i++ ) - { - theta = 1.0 - tau + A[i] * pow( pow( delta - 1.0, 2.0 ), 1.0 / (2.0 * beta[i])); - Delta = pow( theta, 2.0 ) + B[i] * pow( pow( delta - 1.0, 2.0 ), a[i] ); - - Phi = exp( -C[i] * pow( delta - 1.0, 2.0 ) - D[i] * pow( tau - 1.0, 2.0 )); - - dPhi_delta = -2.0 * C[i] * (delta - 1.0) * Phi; - - dDelta_delta = (delta - 1.0) * - (A[i] * theta * 2.0 / beta[i] * - pow( pow( delta - 1.0, 2.0 ), 1.0 / (2.0 * beta[i]) - 1.0 ) + 2.0 * B[i] * a[i] * pow( pow( delta - 1.0, 2.0 ), a[i] - 1.0 )); - - dDelta_delta_b = b[i] * pow( Delta, b[i] - 1.0 ) * dDelta_delta; - - phi_r_delta += n[i] * (pow( Delta, b[i] ) * (Phi + delta *dPhi_delta) + dDelta_delta_b * delta * Phi); - } - - // Helmholtz energy equation: see equation (2.2) from Span and Wagner (1996) - return rho * (1.0 + delta * phi_r_delta) / (P / (R * T)) - 1.0; -} - -} - -SpanWagnerCO2Density::SpanWagnerCO2Density( array1d< string > const & inputPara, - array1d< string > const & componentNames, - array1d< real64 > const & componentMolarWeight ): - PVTFunctionBase( inputPara[1], - componentNames, - componentMolarWeight ) -{ - - bool notFound = true; - for( localIndex i = 0; i < componentNames.size(); ++i ) - { - if( componentNames[i] == "CO2" || componentNames[i] == "co2" ) - { - m_CO2Index = i; - notFound = false; - break; - } - } - GEOSX_ERROR_IF( notFound, "Component CO2 is not found!" ); - - makeTable( inputPara ); -} - -void SpanWagnerCO2Density::makeTable( array1d< string > const & inputPara ) -{ - array1d< array1d< real64 > > coordinates; - coordinates.resize( 2 ); - - real64 TStart = -1.0; - real64 TEnd = -1.0; - real64 dT = -1.0; - real64 PStart = -1.0; - real64 PEnd = -1.0; - real64 dP = -1.0; - - GEOSX_ERROR_IF( inputPara.size() < 8, "Invalid SpanWagnerCO2Density input!" ); - - try - { - PStart = stod( inputPara[2] ); - PEnd = stod( inputPara[3] ); - dP = stod( inputPara[4] ); - - TStart = stod( inputPara[5] ); - TEnd = stod( inputPara[6] ); - dT = stod( inputPara[7] ); - } - catch( const std::invalid_argument & e ) - { - GEOSX_ERROR( "Invalid SpanWagnerCO2Density argument:" + string( e.what()) ); - } - - real64 P = PStart; - while( P <= PEnd ) - { - coordinates[0].emplace_back( P ); - P += dP; - } - - real64 T = TStart; - while( T <= TEnd ) - { - coordinates[1].emplace_back( T ); - T += dT; - } - - localIndex const nP = coordinates[0].size(); - localIndex const nT = coordinates[1].size(); - array1d< real64 > values( nP * nT ); - calculateCO2Density( coordinates, values ); - - FunctionManager & functionManager = getGlobalState().getFunctionManager(); - m_CO2DensityTable = dynamicCast< TableFunction * >( functionManager.createChild( "TableFunction", "CO2DensityTable" ) ); - m_CO2DensityTable->setTableCoordinates( coordinates ); - m_CO2DensityTable->setTableValues( values ); - m_CO2DensityTable->reInitializeFunction(); - m_CO2DensityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); -} - - -void SpanWagnerCO2Density::calculateCO2Density( array1d< array1d< real64 > > const & coordinates, - array1d< real64 > const & values ) -{ - - constexpr real64 TK_f = 273.15; - - localIndex const numPressures = coordinates[0].size(); - localIndex const numTemperatures = coordinates[1].size(); - - for( localIndex i = 0; i < numPressures; ++i ) - { - real64 const PPa = coordinates[0][i]; - for( localIndex j = 0; j < numTemperatures; ++j ) - { - real64 const TK = coordinates[1][j] + TK_f; - spanWagnerCO2DensityFunction( TK, PPa, values[j*numPressures+i], &detail::f ); - } - } -} - -void SpanWagnerCO2Density::spanWagnerCO2DensityFunction( real64 const & T, - real64 const & P, - real64 & rho, - real64 (*f)( real64 const & x1, real64 const & x2, real64 const & x3 ) ) -{ - constexpr real64 P_Pa_f = 1e+5; - constexpr real64 P_c = 73.773 * P_Pa_f; - constexpr real64 T_c = 304.1282; - constexpr real64 rho_c = 467.6; - constexpr real64 R = 188.9241; - - constexpr real64 vpa[] = { -7.0602087, 1.9391218, -1.6463597, -3.2995634 }; - constexpr real64 vpt[] = { 1.0, 1.5, 2.0, 4.0 }; - - constexpr real64 lda[] = { 1.9245108, -0.62385555, -0.32731127, 0.39245142 }; - constexpr real64 ldt[] = { 0.340, 0.5, 1.6666666667, 1.833333333 }; - - real64 const eps = 1e-10; - real64 const dx = 1e-10; - int count = 0; - - // initial guess - if( T < T_c ) - { - real64 sum = 0; - for( int i=0; i < 4; i++ ) - { - sum += vpa[i] * pow( 1.0 - T / T_c, vpt[i] ); - } - real64 const psat = P_c * exp( T_c / T * sum ); - - sum = 0; - for( int i=0; i < 4; i++ ) - { - sum += lda[i] * pow( 1.0 - T / T_c, ldt[i] ); - } - real64 const denl = rho_c * exp( sum ); - - if( P >= psat ) - { - rho = denl; - } - else - { - rho = P / (R * T); - } - } - else - { - rho = 1.0 / (30.0 + R * T / P); - } - - // Newton loop - for(;; ) - { - real64 const v0 = (*f)( T, P, rho ); - real64 const v1 = (*f)( T, P, rho+dx ); - real64 const dre = -v0/((v1-v0)/dx); - if( fabs( dre ) < eps ) - { - break; - } - - GEOSX_ERROR_IF( count > 50, "SpanWagnerCO2Density NR convergence fails! " << "dre = " << dre << ", eps = " << eps ); - - count++; - rho += dre; - } -} - -SpanWagnerCO2Density::KernelWrapper SpanWagnerCO2Density::createKernelWrapper() -{ - return KernelWrapper( m_componentNames, - m_componentMolarWeight, - m_CO2DensityTable, - m_CO2Index ); -} - -REGISTER_CATALOG_ENTRY( PVTFunctionBase, SpanWagnerCO2Density, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) - -} // namespace PVTProps - -} // namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.hpp deleted file mode 100644 index c5aed105277..00000000000 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.hpp +++ /dev/null @@ -1,165 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * 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 Total, S.A - * Copyright (c) 2019- GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file SpanWagnerCO2Density.hpp - */ - -#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_SPANWAGNERCO2DENSITY_HPP_ -#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_SPANWAGNERCO2DENSITY_HPP_ - -#include "NewPVTFunctionBase.hpp" - -#include "managers/Functions/TableFunction.hpp" - -namespace geosx -{ - -namespace PVTProps -{ - -class SpanWagnerCO2DensityUpdate final : public PVTFunctionBaseUpdate -{ -public: - - SpanWagnerCO2DensityUpdate( arrayView1d< string const > const & componentNames, - arrayView1d< real64 const > const & componentMolarWeight, - TableFunction * CO2DensityTable, - localIndex const CO2Index ) - : PVTFunctionBaseUpdate( componentNames, - componentMolarWeight ), - m_CO2DensityTable( CO2DensityTable->createKernelWrapper() ), - m_CO2Index( CO2Index ) - {} - - /// Default copy constructor - SpanWagnerCO2DensityUpdate( SpanWagnerCO2DensityUpdate const & ) = default; - - /// Default move constructor - SpanWagnerCO2DensityUpdate( SpanWagnerCO2DensityUpdate && ) = default; - - /// Deleted copy assignment operator - SpanWagnerCO2DensityUpdate & operator=( SpanWagnerCO2DensityUpdate const & ) = delete; - - /// Deleted move assignment operator - SpanWagnerCO2DensityUpdate & operator=( SpanWagnerCO2DensityUpdate && ) = delete; - - GEOSX_HOST_DEVICE - GEOSX_FORCE_INLINE - virtual void compute( real64 const & pressure, - real64 const & temperature, - arraySlice1d< real64 const > const & phaseComposition, - real64 & value, - real64 & dValue_dPressure, - real64 & dValue_dTemperature, - arraySlice1d< real64 > const & dValue_dPhaseComposition, - bool useMass = 0 ) const override; - -protected: - - /// Table with brine density tabulated as a function (P,T,sal) - TableFunction::KernelWrapper const m_CO2DensityTable; - - /// Index of the CO2 component - localIndex const m_CO2Index; - -}; - -class SpanWagnerCO2Density : public PVTFunctionBase -{ -public: - - SpanWagnerCO2Density( array1d< string > const & inputPara, - array1d< string > const & componentNames, - array1d< real64 > const & componentMolarWeight ); - - ~SpanWagnerCO2Density() override {} - - static string catalogName() { return "NewSpanWagnerCO2Density"; } - - virtual string getCatalogName() const override final { return catalogName(); } - - virtual PVTFunctionType functionType() const override - { - return PVTFunctionType::DENSITY; - } - - /// Type of kernel wrapper for in-kernel update - using KernelWrapper = SpanWagnerCO2DensityUpdate; - - /** - * @brief Create an update kernel wrapper. - * @return the wrapper - */ - KernelWrapper createKernelWrapper(); - - static - void calculateCO2Density( array1d< array1d< real64 > > const & coordinates, - array1d< real64 > const & values ); - -private: - - void makeTable( array1d< string > const & inputPara ); - - static - void spanWagnerCO2DensityFunction( real64 const & T, - real64 const & P, - real64 & rho, - real64 (*f)( real64 const & x1, real64 const & x2, real64 const & x3 ) ); - - /// Table with CO2 density tabulated as a function of (P,T) - TableFunction * m_CO2DensityTable; - - /// Index of the CO2 component - localIndex m_CO2Index; - -}; - -GEOSX_HOST_DEVICE -GEOSX_FORCE_INLINE -void SpanWagnerCO2DensityUpdate::compute( real64 const & pressure, - real64 const & temperature, - arraySlice1d< real64 const > const & phaseComposition, - real64 & value, - real64 & dValue_dPressure, - real64 & dValue_dTemperature, - arraySlice1d< real64 > const & dValue_dPhaseComposition, - bool useMass ) const -{ - GEOSX_UNUSED_VAR( phaseComposition ); - - real64 const input[2] = { pressure, temperature }; - real64 densityDeriv[2]{}; - m_CO2DensityTable.compute( input, value, densityDeriv ); - dValue_dPressure = densityDeriv[0]; - dValue_dTemperature = densityDeriv[1]; - - if( !useMass ) - { - value /= m_componentMolarWeight[m_CO2Index]; - dValue_dPressure /= m_componentMolarWeight[m_CO2Index]; - dValue_dTemperature /= m_componentMolarWeight[m_CO2Index]; - } - - for( real64 & val : dValue_dPhaseComposition ) - { - val = 0.0; - } -} - -} // end namespace PVTProps - -} // end namespace geosx - -#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_SPANWAGNERCO2DENSITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionBase.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionBase.hpp index f1c2aed8731..c44cde75d3d 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionBase.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionBase.hpp @@ -13,14 +13,14 @@ */ /** - * @file PVTFunctionBase.hpp + * @file NewPVTFunctionBase.hpp */ -#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_PVTFUNCTIONBASE_HPP_ -#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_PVTFUNCTIONBASE_HPP_ +#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWPVTFUNCTIONBASE_HPP_ +#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWPVTFUNCTIONBASE_HPP_ -#include "constitutive/fluid/PVTFunctions/UtilityFunctions.hpp" #include "codingUtilities/StringUtilities.hpp" +#include "dataRepository/ObjectCatalog.hpp" namespace geosx { @@ -28,57 +28,96 @@ namespace geosx namespace PVTProps { -enum class PVTFuncType {UNKNOWN, DENSITY, VISCOSITY}; +enum class PVTFunctionType { UNKNOWN, DENSITY, VISCOSITY }; -class PVTFunction +class PVTFunctionBaseUpdate { public: + PVTFunctionBaseUpdate( arrayView1d< string const > const & componentNames, + arrayView1d< real64 const > const & componentMolarWeight ) + : + m_componentNames( componentNames ), + m_componentMolarWeight( componentMolarWeight ) + {} + + /// Default copy constructor + PVTFunctionBaseUpdate( PVTFunctionBaseUpdate const & ) = default; + + /// Default move constructor + PVTFunctionBaseUpdate( PVTFunctionBaseUpdate && ) = default; + + /// Deleted copy assignment operator + PVTFunctionBaseUpdate & operator=( PVTFunctionBaseUpdate const & ) = delete; + + /// Deleted move assignment operator + PVTFunctionBaseUpdate & operator=( PVTFunctionBaseUpdate && ) = delete; + + GEOSX_HOST_DEVICE + virtual void compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & phaseComposition, + real64 & value, + real64 & dValue_dPresure, + real64 & dValue_dTemperature, + arraySlice1d< real64 > const & dValue_dPhaseComposition, + bool useMass = 0 ) const = 0; + +protected: + + /// Array storing the name of the components + arrayView1d< string const > m_componentNames; + + /// Array storing the component molar weights + arrayView1d< real64 const > m_componentMolarWeight; + +}; + +class PVTFunctionBase +{ - PVTFunction( string const & name, string_array const & componentNames, real64_array const & componentMolarWeight ): +public: + + PVTFunctionBase( string const & name, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ) + : m_functionName( name ), m_componentNames( componentNames ), m_componentMolarWeight( componentMolarWeight ) {} - virtual ~PVTFunction(){} - + virtual ~PVTFunctionBase() = default; - using CatalogInterface = dataRepository::CatalogInterface< PVTFunction, string_array const &, - string_array const &, - real64_array const & >; + using CatalogInterface = dataRepository::CatalogInterface< PVTFunctionBase, array1d< string > const &, + array1d< string > const &, + array1d< real64 > const & >; static typename CatalogInterface::CatalogType & getCatalog() { static CatalogInterface::CatalogType catalog; return catalog; } - virtual string getCatalogName() const = 0; + virtual string getCatalogName() const = 0; - string const & functionName() const - { - return m_functionName; - } - - virtual PVTFuncType functionType() const = 0; - - //phase density/viscosity - //input: P, T, phaseCompFraction - //output: phase density/viscoty + string const & functionName() const { return m_functionName; } - virtual void evaluation( EvalVarArgs const & pressure, EvalVarArgs const & temperature, arraySlice1d< EvalVarArgs const > const & phaseComposition, - EvalVarArgs & value, bool useMass = 0 ) const = 0; + virtual PVTFunctionType functionType() const = 0; protected: + /// Name of the PVT function string m_functionName; - string_array m_componentNames; - real64_array m_componentMolarWeight; + /// Array storing the name of the components + array1d< string > m_componentNames; + + /// Array storing the component molar weights + array1d< real64 > m_componentMolarWeight; }; -} +} // end namespace PVTProps -} +} // end namespace geosx -#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_PVTFUNCTIONBASE_HPP_ +#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWPVTFUNCTIONBASE_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp index 5b5a75ee06f..93e2abf1fd1 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp @@ -13,12 +13,14 @@ */ /** - * @file SpanWagnerCO2DensityFunction.cpp + * @file SpanWagnerCO2Density.cpp */ - #include "constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp" +#include "managers/Functions/FunctionManager.hpp" +#include "managers/GeosxState.hpp" + namespace geosx { @@ -27,9 +29,15 @@ using namespace stringutilities; namespace PVTProps { -//calc density based on table 3 -real64 f( const real64 & T, const real64 & P, const real64 & rho ) +namespace detail { + +real64 f( real64 const & T, + real64 const & P, + real64 const & rho ) +{ + // all the coefficients below are defined in Table (31) of Span and Wagner (1996) + // the variable names used below follow the notation of the Table constexpr real64 n[] = {0.38856823203161, 2.938547594274, -5.5867188534934, -0.76753199592477, 0.31729005580416, 0.54803315897767, 0.12279411220335, 2.165896154322, 1.5841735109724, -0.23132705405503, 0.058116916431436, -0.55369137205382, 0.48946615909422, -0.024275739843501, 0.062494790501678, -0.12175860225246, @@ -74,11 +82,13 @@ real64 f( const real64 & T, const real64 & P, const real64 & rho ) constexpr real64 R = 188.9241; - real64 tau = T_c / T; - real64 delta = rho / rho_c; + real64 const tau = T_c / T; + real64 const delta = rho / rho_c; real64 theta, Delta, Phi, dPhi_delta, dDelta_delta, dDelta_delta_b; + // residual part of the energy equation + // this is defined in Table (32) of Span and Wagner (1996) real64 phi_r_delta = 0.0; for( int i=0; i<7; i++ ) @@ -120,57 +130,51 @@ real64 f( const real64 & T, const real64 & P, const real64 & rho ) phi_r_delta += n[i] * (pow( Delta, b[i] ) * (Phi + delta *dPhi_delta) + dDelta_delta_b * delta * Phi); } + // Helmholtz energy equation: see equation (2.2) from Span and Wagner (1996) return rho * (1.0 + delta * phi_r_delta) / (P / (R * T)) - 1.0; } +} -SpanWagnerCO2DensityFunction::SpanWagnerCO2DensityFunction( string_array const & inputPara, string_array const & componentNames, - real64_array const & componentMolarWeight ): PVTFunction( inputPara[1], componentNames, - componentMolarWeight ) +SpanWagnerCO2Density::SpanWagnerCO2Density( array1d< string > const & inputPara, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ): + PVTFunctionBase( inputPara[1], + componentNames, + componentMolarWeight ) { - bool notFound = 1; - + bool notFound = true; for( localIndex i = 0; i < componentNames.size(); ++i ) { - - if( streq( componentNames[i], "CO2" ) || streq( componentNames[i], "co2" )) + if( componentNames[i] == "CO2" || componentNames[i] == "co2" ) { m_CO2Index = i; - notFound = 0; + notFound = false; break; } - } - GEOSX_ERROR_IF( notFound, "Component CO2 is not found!" ); makeTable( inputPara ); - } -void SpanWagnerCO2DensityFunction::makeTable( string_array const & inputPara ) +void SpanWagnerCO2Density::makeTable( array1d< string > const & inputPara ) { + array1d< array1d< real64 > > coordinates; + coordinates.resize( 2 ); - real64_array pressures; - real64_array temperatures; - - real64 PStart, PEnd, dP; - real64 TStart, TEnd, dT; - real64 P, T; - - dT = -1.0; - dP = -1.0; - TStart = -1.0; - TEnd = -1.0; - PStart = -1.0; - PEnd = -1.0; + real64 TStart = -1.0; + real64 TEnd = -1.0; + real64 dT = -1.0; + real64 PStart = -1.0; + real64 PEnd = -1.0; + real64 dP = -1.0; GEOSX_ERROR_IF( inputPara.size() < 8, "Invalid SpanWagnerCO2Density input!" ); try { - PStart = stod( inputPara[2] ); PEnd = stod( inputPara[3] ); dP = stod( inputPara[4] ); @@ -178,159 +182,97 @@ void SpanWagnerCO2DensityFunction::makeTable( string_array const & inputPara ) TStart = stod( inputPara[5] ); TEnd = stod( inputPara[6] ); dT = stod( inputPara[7] ); - } catch( const std::invalid_argument & e ) { - - GEOSX_ERROR( "Invalid SpanWagnerCO2Density argument:" + string( e.what())); - + GEOSX_ERROR( "Invalid SpanWagnerCO2Density argument:" + string( e.what()) ); } - P = PStart; - + real64 P = PStart; while( P <= PEnd ) { - - pressures.emplace_back( P ); + coordinates[0].emplace_back( P ); P += dP; - } - T = TStart; - + real64 T = TStart; while( T <= TEnd ) { - - temperatures.emplace_back( T ); + coordinates[1].emplace_back( T ); T += dT; - } - localIndex nP = pressures.size(); - localIndex nT = temperatures.size(); - - real64_array2d densities( nP, nT ); - - calculateCO2Density( pressures, temperatures, densities ); - - m_CO2DensityTable = std::make_shared< XYTable >( "SpanWagnerCO2DensityTable", pressures, temperatures, densities ); - - + localIndex const nP = coordinates[0].size(); + localIndex const nT = coordinates[1].size(); + array1d< real64 > values( nP * nT ); + calculateCO2Density( coordinates, values ); + + FunctionManager & functionManager = getGlobalState().getFunctionManager(); + m_CO2DensityTable = dynamicCast< TableFunction * >( functionManager.createChild( "TableFunction", "CO2DensityTable" ) ); + m_CO2DensityTable->setTableCoordinates( coordinates ); + m_CO2DensityTable->setTableValues( values ); + m_CO2DensityTable->reInitializeFunction(); + m_CO2DensityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); } -void SpanWagnerCO2DensityFunction::evaluation( EvalVarArgs const & pressure, EvalVarArgs const & temperature, arraySlice1d< EvalVarArgs const > const & GEOSX_UNUSED_PARAM( - phaseComposition ), EvalVarArgs & value, bool useMass ) const +void SpanWagnerCO2Density::calculateCO2Density( array1d< array1d< real64 > > const & coordinates, + array1d< real64 > const & values ) { - EvalArgs2D P, T, density; - P.m_var = pressure.m_var; - P.m_der[0] = 1.0; + constexpr real64 TK_f = 273.15; - T.m_var = temperature.m_var; - T.m_der[1] = 1.0; + localIndex const numPressures = coordinates[0].size(); + localIndex const numTemperatures = coordinates[1].size(); - density = m_CO2DensityTable->value( P, T ); - - real64 CO2MW = m_componentMolarWeight[m_CO2Index]; - - if( !useMass ) + for( localIndex i = 0; i < numPressures; ++i ) { - - density /= CO2MW; - - } - - value.m_var = density.m_var; - value.m_der[0] = density.m_der[0]; - -} - -void SpanWagnerCO2DensityFunction::calculateCO2Density( real64_array const & pressure, real64_array const & temperature, real64_array2d const & density ) -{ - - constexpr real64 T_K_f = 273.15; - - real64 PPa, TK; - - for( localIndex i = 0; i < pressure.size(); ++i ) - { - - PPa = pressure[i]; - - for( localIndex j = 0; j < temperature.size(); ++j ) + real64 const PPa = coordinates[0][i]; + for( localIndex j = 0; j < numTemperatures; ++j ) { - - TK = temperature[j] + T_K_f; - - spanWagnerCO2Density( TK, PPa, density[i][j], &f ); - + real64 const TK = coordinates[1][j] + TK_f; + spanWagnerCO2DensityFunction( TK, PPa, values[j*numPressures+i], &detail::f ); } - } } -void SpanWagnerCO2DensityFunction::spanWagnerCO2Density( real64 const & T, real64 const & P, real64 & rho, real64 (*f)( real64 const & x1, real64 const & x2, - real64 const & x3 )) +void SpanWagnerCO2Density::spanWagnerCO2DensityFunction( real64 const & T, + real64 const & P, + real64 & rho, + real64 (*f)( real64 const & x1, real64 const & x2, real64 const & x3 ) ) { constexpr real64 P_Pa_f = 1e+5; - constexpr real64 P_c = 73.773 * P_Pa_f; constexpr real64 T_c = 304.1282; constexpr real64 rho_c = 467.6; - constexpr real64 R = 188.9241; - // constexpr real64 Rgas = 8.314467; - - // constexpr real64 V_c = Rgas*T_c/P_c; - - - constexpr real64 vpa[] = {-7.0602087, 1.9391218, -1.6463597, -3.2995634}; - constexpr real64 vpt[] = {1.0, 1.5, 2.0, 4.0}; - - constexpr real64 lda[] = {1.9245108, -0.62385555, -0.32731127, 0.39245142}; - constexpr real64 ldt[] = {0.340, 0.5, 1.6666666667, 1.833333333}; - - // constexpr real64 vda[] = {-1.7074879, -0.82274670, -4.6008549, -10.111178, -29.742252}; - // constexpr real64 vdt[] = {0.340, 0.5, 1.0, 2.3333333333, 4.6666666667}; + constexpr real64 vpa[] = { -7.0602087, 1.9391218, -1.6463597, -3.2995634 }; + constexpr real64 vpt[] = { 1.0, 1.5, 2.0, 4.0 }; + constexpr real64 lda[] = { 1.9245108, -0.62385555, -0.32731127, 0.39245142 }; + constexpr real64 ldt[] = { 0.340, 0.5, 1.6666666667, 1.833333333 }; - real64 eps = 1e-10; + real64 const eps = 1e-10; + real64 const dx = 1e-10; int count = 0; - real64 dx = 1e-10; - real64 dre, sum; - - real64 psat, denl; - - //initial guess + // initial guess if( T < T_c ) { - sum = 0; - for( int i=0; i<4; i++ ) + real64 sum = 0; + for( int i=0; i < 4; i++ ) { sum += vpa[i] * pow( 1.0 - T / T_c, vpt[i] ); } - - psat = P_c * exp( T_c / T * sum ); + real64 const psat = P_c * exp( T_c / T * sum ); sum = 0; - for( int i=0; i<4; i++ ) + for( int i=0; i < 4; i++ ) { sum += lda[i] * pow( 1.0 - T / T_c, ldt[i] ); } - - denl = rho_c * exp( sum ); - - /* - sum = 0; - for(int i=0; i<5; i++) - sum += vda[i] * pow(1.0 - T / T_c, vdt[i]); - - denv = rho_c * exp(sum); - */ + real64 const denl = rho_c * exp( sum ); if( P >= psat ) { @@ -346,31 +288,34 @@ void SpanWagnerCO2DensityFunction::spanWagnerCO2Density( real64 const & T, real6 rho = 1.0 / (30.0 + R * T / P); } - real64 v1, v0; - + // Newton loop for(;; ) { - v0 = (*f)( T, P, rho ); - v1 = (*f)( T, P, rho+dx ); - dre = -v0/((v1-v0)/dx); - + real64 const v0 = (*f)( T, P, rho ); + real64 const v1 = (*f)( T, P, rho+dx ); + real64 const dre = -v0/((v1-v0)/dx); if( fabs( dre ) < eps ) + { break; + } GEOSX_ERROR_IF( count > 50, "SpanWagnerCO2Density NR convergence fails! " << "dre = " << dre << ", eps = " << eps ); count++; - rho += dre; } } +SpanWagnerCO2Density::KernelWrapper SpanWagnerCO2Density::createKernelWrapper() +{ + return KernelWrapper( m_componentNames, + m_componentMolarWeight, + m_CO2DensityTable, + m_CO2Index ); +} +REGISTER_CATALOG_ENTRY( PVTFunctionBase, SpanWagnerCO2Density, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) -REGISTER_CATALOG_ENTRY( PVTFunction, - SpanWagnerCO2DensityFunction, - string_array const &, string_array const &, real64_array const & ) - -} +} // namespace PVTProps -} +} // namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp index 5b7700653b6..c41aa07a216 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp @@ -13,61 +13,153 @@ */ /** - * @file SpanWagnerCO2DensityFunction.hpp + * @file SpanWagnerCO2Density.hpp */ -#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_SPANWAGNERCO2DENSITYFUNCTION_HPP_ -#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_SPANWAGNERCO2DENSITYFUNCTION_HPP_ +#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_SPANWAGNERCO2DENSITY_HPP_ +#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_SPANWAGNERCO2DENSITY_HPP_ #include "PVTFunctionBase.hpp" +#include "managers/Functions/TableFunction.hpp" + namespace geosx { namespace PVTProps { -class SpanWagnerCO2DensityFunction : public PVTFunction +class SpanWagnerCO2DensityUpdate final : public PVTFunctionBaseUpdate { public: + SpanWagnerCO2DensityUpdate( arrayView1d< string const > const & componentNames, + arrayView1d< real64 const > const & componentMolarWeight, + TableFunction * CO2DensityTable, + localIndex const CO2Index ) + : PVTFunctionBaseUpdate( componentNames, + componentMolarWeight ), + m_CO2DensityTable( CO2DensityTable->createKernelWrapper() ), + m_CO2Index( CO2Index ) + {} - SpanWagnerCO2DensityFunction( string_array const & inputPara, - string_array const & componentNames, - real64_array const & componentMolarWeight ); + /// Default copy constructor + SpanWagnerCO2DensityUpdate( SpanWagnerCO2DensityUpdate const & ) = default; - ~SpanWagnerCO2DensityFunction() override {} + /// Default move constructor + SpanWagnerCO2DensityUpdate( SpanWagnerCO2DensityUpdate && ) = default; + /// Deleted copy assignment operator + SpanWagnerCO2DensityUpdate & operator=( SpanWagnerCO2DensityUpdate const & ) = delete; - static constexpr auto m_catalogName = "SpanWagnerCO2Density"; - static string catalogName() { return m_catalogName; } - virtual string getCatalogName() const override final { return catalogName(); } + /// Deleted move assignment operator + SpanWagnerCO2DensityUpdate & operator=( SpanWagnerCO2DensityUpdate && ) = delete; + + GEOSX_HOST_DEVICE + GEOSX_FORCE_INLINE + virtual void compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & phaseComposition, + real64 & value, + real64 & dValue_dPressure, + real64 & dValue_dTemperature, + arraySlice1d< real64 > const & dValue_dPhaseComposition, + bool useMass = 0 ) const override; + +protected: + + /// Table with brine density tabulated as a function (P,T,sal) + TableFunction::KernelWrapper const m_CO2DensityTable; + + /// Index of the CO2 component + localIndex const m_CO2Index; + +}; + +class SpanWagnerCO2Density : public PVTFunctionBase +{ +public: + + SpanWagnerCO2Density( array1d< string > const & inputPara, + array1d< string > const & componentNames, + array1d< real64 > const & componentMolarWeight ); + + ~SpanWagnerCO2Density() override {} + static string catalogName() { return "SpanWagnerCO2Density"; } - virtual PVTFuncType functionType() const override + virtual string getCatalogName() const override final { return catalogName(); } + + virtual PVTFunctionType functionType() const override { - return PVTFuncType::DENSITY; + return PVTFunctionType::DENSITY; } - virtual void evaluation( EvalVarArgs const & pressure, EvalVarArgs const & temperature, arraySlice1d< EvalVarArgs const > const & phaseComposition, - EvalVarArgs & value, bool useMass = 0 ) const override; + /// Type of kernel wrapper for in-kernel update + using KernelWrapper = SpanWagnerCO2DensityUpdate; - static void calculateCO2Density( real64_array const & pressure, real64_array const & temperature, real64_array2d const & density ); + /** + * @brief Create an update kernel wrapper. + * @return the wrapper + */ + KernelWrapper createKernelWrapper(); + + static + void calculateCO2Density( array1d< array1d< real64 > > const & coordinates, + array1d< real64 > const & values ); private: - void makeTable( string_array const & inputPara ); + void makeTable( array1d< string > const & inputPara ); - static void spanWagnerCO2Density( real64 const & T, real64 const & P, real64 & rho, real64 (*f)( real64 const & x1, real64 const & x2, real64 const & x3 )); + static + void spanWagnerCO2DensityFunction( real64 const & T, + real64 const & P, + real64 & rho, + real64 (*f)( real64 const & x1, real64 const & x2, real64 const & x3 ) ); + /// Table with CO2 density tabulated as a function of (P,T) + TableFunction * m_CO2DensityTable; - TableFunctionPtr m_CO2DensityTable; + /// Index of the CO2 component localIndex m_CO2Index; }; -} +GEOSX_HOST_DEVICE +GEOSX_FORCE_INLINE +void SpanWagnerCO2DensityUpdate::compute( real64 const & pressure, + real64 const & temperature, + arraySlice1d< real64 const > const & phaseComposition, + real64 & value, + real64 & dValue_dPressure, + real64 & dValue_dTemperature, + arraySlice1d< real64 > const & dValue_dPhaseComposition, + bool useMass ) const +{ + GEOSX_UNUSED_VAR( phaseComposition ); + + real64 const input[2] = { pressure, temperature }; + real64 densityDeriv[2]{}; + m_CO2DensityTable.compute( input, value, densityDeriv ); + dValue_dPressure = densityDeriv[0]; + dValue_dTemperature = densityDeriv[1]; + if( !useMass ) + { + value /= m_componentMolarWeight[m_CO2Index]; + dValue_dPressure /= m_componentMolarWeight[m_CO2Index]; + dValue_dTemperature /= m_componentMolarWeight[m_CO2Index]; + } + + for( real64 & val : dValue_dPhaseComposition ) + { + val = 0.0; + } } -#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_SPANWAGNERCO2DENSITYFUNCTION_HPP_ +} // end namespace PVTProps + +} // end namespace geosx + +#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_SPANWAGNERCO2DENSITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/UtilityFunctions.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/UtilityFunctions.cpp deleted file mode 100644 index 2f3146004a6..00000000000 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/UtilityFunctions.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * 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 Total, S.A - * Copyright (c) 2019- GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file UtilityFunctions.cpp - */ - - -#include "constitutive/fluid/PVTFunctions/UtilityFunctions.hpp" - -namespace geosx -{ - -namespace PVTProps -{ - -EvalArgs2D XYTable::value( EvalArgs2D const & x, EvalArgs2D const & y ) const -{ - localIndex_array xIndices( 2 ), yIndices( 2 ); - - //find i index - - if( x <= m_x[0] ) - { - xIndices[0] = 0; - } - else if( x >= m_x[m_x.size()-2] ) - { - xIndices[0] = m_x.size()-2; - } - else - { - for( localIndex i = 1; i < m_x.size(); ++i ) - { - if( x <= m_x[i] ) - { - xIndices[0] = i - 1; - break; - } - } - } - - xIndices[1] = xIndices[0] + 1; - - EvalArgs2D xWeight = (x - m_x[xIndices[0] ]) / (m_x[xIndices[1] ] - m_x[xIndices[0] ]); - - //find j index - - if( y <= m_y[0] ) - { - yIndices[0] = 0; - } - else if( y >= m_y[m_y.size()-2] ) - { - yIndices[0] = m_y.size()-2; - } - else - { - for( localIndex i = 1; i < m_y.size(); ++i ) - { - - if( y <= m_y[i] ) - { - yIndices[0] = i - 1; - break; - } - } - } - - yIndices[1] = yIndices[0] + 1; - - EvalArgs2D yWeight = (y - m_y[yIndices[0] ]) / (m_y[yIndices[1] ] - m_y[yIndices[0] ]); - - EvalArgs2D out = m_value[xIndices[0] ][yIndices[0] ] * (1.0 - xWeight) * (1.0 - yWeight) + m_value[xIndices[0] ][yIndices[1] ] * (1.0 - xWeight) * yWeight + - m_value[xIndices[1] ][yIndices[1] ] * xWeight * yWeight + m_value[xIndices[1] ][yIndices[0] ] * xWeight * (1.0 - yWeight); - - return out; -} - - -template< class T > -T XTable::getValue( T const & x ) const -{ - - localIndex idx = 0; - //find i index - - if( x <= m_x[0] ) - { - idx = 0; - } - else if( x >= m_x[m_x.size()-1] ) - { - idx = m_x.size()-2; - } - else - { - for( localIndex i = 1; i < m_x.size(); ++i ) - { - if( x <= m_x[i] ) - { - idx = i - 1; - break; - } - } - } - - T weight = (x - m_x[idx]) / (m_x[idx + 1] - m_x[idx]); - - T out = m_value[idx] * (1.0 - weight) + m_value[idx + 1] * weight; - - return out; -} - - -} // namespace PVTProps -} // namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/UtilityFunctions.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/UtilityFunctions.hpp deleted file mode 100644 index be0b247df0b..00000000000 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/UtilityFunctions.hpp +++ /dev/null @@ -1,549 +0,0 @@ -/* - * ------------------------------------------------------------------------------------------------------------ - * 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 Total, S.A - * Copyright (c) 2019- GEOSX Contributors - * All rights reserved - * - * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. - * ------------------------------------------------------------------------------------------------------------ - */ - -/** - * @file TableFunction.hpp - */ - -#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_UTILITYFUNCTION_HPP_ -#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_UTILITYFUNCTION_HPP_ - -#include "common/DataTypes.hpp" -#include "constitutive/fluid/MultiFluidBase.hpp" - -namespace geosx -{ - -namespace PVTProps -{ - -constexpr localIndex MAX_VAR_DIM = 10; - -template< typename T, int Dim > -class EvalArgs -{ -public: - - EvalArgs() - { - m_var = 0.0; - for( int i = 0; i < Dim; ++i ) - { - m_der[i] = 0; - } - } - - ~EvalArgs() = default; - - EvalArgs( const EvalArgs & arg ) - { - m_var = arg.m_var; - for( int i = 0; i < Dim; ++i ) - { - m_der[i] = arg.m_der[i]; - } - } - - EvalArgs( const T & var ) - { - m_var = var; - for( int i = 0; i < Dim; ++i ) - { - m_der[i] = 0; - } - } - - EvalArgs & operator+=( const EvalArgs & arg ) - { - this->m_var += arg.m_var; - for( localIndex i = 0; i < Dim; ++i ) - { - this->m_der[i] += arg.m_der[i]; - } - - return *this; - } - - - EvalArgs & operator-=( const EvalArgs & arg ) - { - this->m_var -= arg.m_var; - for( localIndex i = 0; i < Dim; ++i ) - { - this->m_der[i] -= arg.m_der[i]; - } - - return *this; - } - - EvalArgs & operator*=( const EvalArgs & arg ) - { - const T & u = this->m_var; - const T & v = arg.m_var; - for( localIndex i = 0; i < Dim; ++i ) - { - const T & uDer = this->m_der[i]; - const T & vDer = arg.m_der[i]; - - this->m_der[i] = (v * uDer + u * vDer); - } - - this->m_var *= v; - return *this; - } - - - EvalArgs & operator/=( const EvalArgs & arg ) - { - const T & u = this->m_var; - const T & v = arg.m_var; - for( localIndex i = 0; i < Dim; ++i ) - { - const T & uDer = this->m_der[i]; - const T & vDer = arg.m_der[i]; - - this->m_der[i] = (v * uDer - u * vDer) /(v * v); - } - - this->m_var /= v; - return *this; - } - - EvalArgs & exponent( const EvalArgs & arg ) - { - const T & v = arg.m_var; - this->m_var = exp( v ); - for( localIndex i = 0; i < Dim; ++i ) - { - const T & vDer = arg.m_der[i]; - this->m_der[i] = this->m_var * vDer; - } - - return *this; - } - - EvalArgs operator+( const EvalArgs & arg ) const - { - EvalArgs result( *this ); - result += arg; - return result; - } - - EvalArgs operator-( const EvalArgs & arg ) const - { - EvalArgs result( *this ); - result -= arg; - return result; - } - - EvalArgs operator-() const - { - EvalArgs result; - result.m_var = -this->m_var; - for( localIndex i = 0; i < Dim; ++i ) - { - result.m_der[i] = -this->m_der[i]; - } - - return result; - } - - EvalArgs operator*( const EvalArgs & arg ) const - { - EvalArgs result( *this ); - result *= arg; - return result; - } - - EvalArgs operator/( const EvalArgs & arg ) const - { - EvalArgs result( *this ); - result /= arg; - return result; - } - - EvalArgs & operator=( const EvalArgs & arg ) - { - this->m_var = arg.m_var; - for( int i = 0; i < Dim; ++i ) - { - m_der[i] = arg.m_der[i]; - } - - return *this; - } - - bool operator==( const EvalArgs & arg ) const - { - if( this->m_var != arg._m_var ) return false; - - for( localIndex i = 0; i < Dim; ++i ) - { - if( this->m_der[i] != arg.m_der[i] ) return false; - } - - return true; - } - - bool operator!=( const EvalArgs & arg ) const - { - return !(*this == arg); - } - - bool operator>( const EvalArgs & arg ) const - { - return this->m_var > arg.m_var; - } - - bool operator<( const EvalArgs & arg ) const - { - return this->m_var < arg.m_var; - } - - bool operator>=( const EvalArgs & arg ) const - { - return this->m_var >= arg.m_var; - } - - bool operator<=( const EvalArgs & arg ) const - { - return this->m_var <= arg.m_var; - } - - EvalArgs & operator+=( const T & arg ) - { - this->m_var += arg; - return *this; - } - - EvalArgs & operator-=( const T & arg ) - { - this->m_var -= arg; - return *this; - } - - EvalArgs & operator*=( const T & arg ) - { - for( localIndex i = 0; i < Dim; ++i ) - { - this->m_der[i] *= arg; - } - - this->m_var *= arg; - return *this; - } - - EvalArgs & operator/=( const T & arg ) - { - for( localIndex i = 0; i < Dim; ++i ) - { - this->m_der[i] /= arg; - } - - this->m_var /= arg; - return *this; - } - - EvalArgs operator+( const T & arg ) const - { - EvalArgs result( *this ); - result += arg; - return result; - } - - EvalArgs operator-( const T & arg ) const - { - EvalArgs result( *this ); - result -= arg; - return result; - } - - EvalArgs operator*( const T & arg ) const - { - EvalArgs result( *this ); - result *= arg; - return result; - } - - EvalArgs operator/( const T & arg ) const - { - EvalArgs result( *this ); - result /= arg; - return result; - } - - EvalArgs & operator=( const T & arg ) - { - m_var = arg; - for( int i = 0; i < Dim; ++i ) - { - m_der[i] = 0; - } - return *this; - } - - bool operator==( const T & arg ) const - { - return this->m_var == arg; - } - - bool operator!=( const T & arg ) const - { - return !(*this == arg); - } - - bool operator>( const T & arg ) const - { - return this->m_var > arg; - } - - bool operator<( const T & arg ) const - { - return this->m_var < arg; - } - - bool operator>=( const T & arg ) const - { - return this->m_var >= arg; - } - bool operator<=( const T & arg ) const - { - return this->m_var <= arg; - } - - T m_var; - T m_der[Dim]; -}; - -template< class T, int Dim > -inline EvalArgs< T, Dim > operator+( const T & arg1, const EvalArgs< T, Dim > & arg2 ) -{ - EvalArgs< T, Dim > result( arg2 ); - result += arg1; - return result; -} - -template< class T, int Dim > -inline EvalArgs< T, Dim > operator-( const T & arg1, const EvalArgs< T, Dim > & arg2 ) -{ - EvalArgs< T, Dim > result( arg2 ); - result.m_var = arg1 - result.m_var; - - for( localIndex i = 0; i < Dim; ++i ) - { - result.m_der[i] = -result.m_der[i]; - } - - return result; -} - -template< class T, int Dim > -inline EvalArgs< T, Dim > operator*( const T & arg1, const EvalArgs< T, Dim > & arg2 ) -{ - EvalArgs< T, Dim > result( arg2 ); - result *= arg1; - return result; -} - -template< class T, int Dim > -inline EvalArgs< T, Dim > operator/( const T & arg1, const EvalArgs< T, Dim > & arg2 ) -{ - EvalArgs< T, Dim > result( arg2 ); - - T coef = -(arg1 / result.m_var / result.m_var); - result.m_var = arg1 / result.m_var; - - for( localIndex i = 0; i < Dim; ++i ) - { - result.m_der[i] = coef * result.m_der[i]; - } - - return result; -} - - -template< class T, int Dim > -inline bool operator==( const T & arg1, const EvalArgs< T, Dim > & arg2 ) -{ - return (arg2 == arg1); -} - -template< class T, int Dim > -inline bool operator!=( const T & arg1, const EvalArgs< T, Dim > & arg2 ) -{ - return (arg2 != arg1); -} - -template< class T, int Dim > -inline bool operator>( const T & arg1, const EvalArgs< T, Dim > & arg2 ) -{ - return arg1 > arg2.m_var; -} - -template< class T, int Dim > -inline bool operator<( const T & arg1, const EvalArgs< T, Dim > & arg2 ) -{ - return arg1 < arg2.m_var; -} - -template< class T, int Dim > -inline bool operator>=( const T & arg1, const EvalArgs< T, Dim > & arg2 ) -{ - return arg1 >= arg2.m_var; -} - - -template< class T, int Dim > -inline bool operator<=( const T & arg1, const EvalArgs< T, Dim > & arg2 ) -{ - return arg1 <= arg2.m_var; -} - -typedef EvalArgs< real64, 1 > EvalArgs1D; -typedef EvalArgs< real64, 2 > EvalArgs2D; -typedef EvalArgs< real64, 3 > EvalArgs3D; -typedef EvalArgs< real64, MAX_VAR_DIM > EvalVarArgs; - -class TableFunctionBase -{ -public: - virtual const string & tableName() const = 0; - virtual ~TableFunctionBase(){} - - virtual EvalArgs1D value( const EvalArgs1D & x ) const = 0; - - virtual EvalArgs2D value( const EvalArgs2D & x ) const = 0; - - virtual EvalArgs2D value( const EvalArgs2D & x, const EvalArgs2D & y ) const = 0; - - virtual void print() const = 0; -}; - - -typedef std::shared_ptr< TableFunctionBase > TableFunctionPtr; - -class XYTable : public TableFunctionBase -{ -public: - - XYTable( string const & tableName, real64_array const & x, real64_array const & y, real64_array2d const & value ): m_tableName( tableName ), m_x( x ), - m_y( y ), m_value( value ) {} - - ~XYTable(){} - - real64_array & xArray() - { - return m_x; - } - - real64_array & yArray() - { - return m_y; - } - - real64_array2d & valueArray() - { - return m_value; - } - - - virtual string const & tableName() const - { - return m_tableName; - } - - - virtual EvalArgs1D value( EvalArgs1D const & ) const - { - return 0; - } - - virtual EvalArgs2D value( EvalArgs2D const & ) const - { - return 0; - } - - virtual EvalArgs2D value( EvalArgs2D const & x, EvalArgs2D const & y ) const; - - virtual void print() const - {} - -private: - - string m_tableName; - real64_array m_x; - real64_array m_y; - real64_array2d m_value; - -}; - -class XTable : public TableFunctionBase -{ -public: - - XTable( string const & tableName, real64_array const & x, real64_array const & value ): m_tableName( tableName ), m_x( x ), m_value( value ) {} - ~XTable(){} - - real64_array & xArray() - { - return m_x; - } - - real64_array & valueArray() - { - return m_value; - } - - virtual string const & tableName() const - { - return m_tableName; - } - - virtual EvalArgs1D value( EvalArgs1D const & x ) const - { - - return getValue< EvalArgs1D >( x ); - - } - - virtual EvalArgs2D value( EvalArgs2D const & x ) const - { - - return getValue< EvalArgs2D >( x ); - - } - - virtual EvalArgs2D value( EvalArgs2D const &, EvalArgs2D const & ) const - { - return 0; - } - -private: - - template< class T > - T getValue( T const & x ) const; - - virtual void print() const - {} - - string m_tableName; - real64_array m_x; - real64_array m_value; - -}; - -} // namespace PVTProps -} // namespace geosx - -#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_UTILITYFUNCTION_HPP_ diff --git a/src/coreComponents/constitutive/fluid/multiFluidSelector.hpp b/src/coreComponents/constitutive/fluid/multiFluidSelector.hpp index 787d4a3ec94..7b8ee2db83b 100644 --- a/src/coreComponents/constitutive/fluid/multiFluidSelector.hpp +++ b/src/coreComponents/constitutive/fluid/multiFluidSelector.hpp @@ -22,7 +22,6 @@ #include "constitutive/fluid/CompositionalMultiphaseFluid.hpp" #include "constitutive/fluid/BlackOilFluid.hpp" #include "constitutive/fluid/MultiPhaseMultiComponentFluid.hpp" -#include "constitutive/fluid/NewMultiPhaseMultiComponentFluid.hpp" namespace geosx { @@ -36,8 +35,7 @@ void constitutiveUpdatePassThru( MultiFluidBase const & fluid, { ConstitutivePassThruHandler< BlackOilFluid, CompositionalMultiphaseFluid, - MultiPhaseMultiComponentFluid, - NewMultiPhaseMultiComponentFluid >::execute( fluid, std::forward< LAMBDA >( lambda ) ); + MultiPhaseMultiComponentFluid >::execute( fluid, std::forward< LAMBDA >( lambda ) ); } template< typename LAMBDA > @@ -46,8 +44,7 @@ void constitutiveUpdatePassThru( MultiFluidBase & fluid, { ConstitutivePassThruHandler< BlackOilFluid, CompositionalMultiphaseFluid, - MultiPhaseMultiComponentFluid, - NewMultiPhaseMultiComponentFluid >::execute( fluid, std::forward< LAMBDA >( lambda ) ); + MultiPhaseMultiComponentFluid >::execute( fluid, std::forward< LAMBDA >( lambda ) ); } } // namespace constitutive diff --git a/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp b/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp index 90732058212..3096ab49b02 100644 --- a/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp +++ b/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp @@ -16,11 +16,7 @@ #include "codingUtilities/UnitTestUtilities.hpp" #include "common/DataTypes.hpp" #include "common/TimingMacros.hpp" -#include "constitutive/fluid/PVTFunctions/NewBrineViscosityFunction.hpp" -#include "constitutive/fluid/PVTFunctions/NewFenghourCO2ViscosityFunction.hpp" -#include "constitutive/fluid/PVTFunctions/NewBrineCO2DensityFunction.hpp" -#include "constitutive/fluid/PVTFunctions/NewSpanWagnerCO2DensityFunction.hpp" -#include "constitutive/fluid/PVTFunctions/NewCO2SolubilityFunction.hpp" +#include "constitutive/fluid/multiFluidSelector.hpp" #include "constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp" #include "constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp" #include "constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp" @@ -49,12 +45,11 @@ static const char * pvtgas_str = "DensityFun SpanWagnerCO2Density 1e6 1.5e7 5e4 static const char * co2flash_str = "FlashModel CO2Solubility 1e6 1.5e7 5e4 94 96 1 0.15"; -// TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION void testValuesAgainstPreviousImplementation( PVTFunctionBaseUpdate const & pvtFunctionWrapper, - PVTFunction const & oldPvtFunction, real64 const pressure, real64 const temperature, arraySlice1d< real64 > const & phaseComposition, + real64 const & oldImplValue, bool const useMass, real64 const relTol ) { @@ -71,29 +66,15 @@ void testValuesAgainstPreviousImplementation( PVTFunctionBaseUpdate const & pvtF dValue_dPhaseComposition, useMass ); - EvalVarArgs oldPres( pressure ); - EvalVarArgs oldTemp( temperature ); - EvalVarArgs oldValue( 0.0 ); - stackArray1d< EvalVarArgs, 2 > oldPhaseComposition( 2 ); - for( localIndex ic = 0; ic < 2; ic++ ) - { - oldPhaseComposition[ic].m_var = phaseComposition[ic]; - } - oldPvtFunction.evaluation( oldPres, - oldTemp, - oldPhaseComposition, - oldValue, - useMass ); - - checkRelativeError( value, oldValue.m_var, relTol ); + checkRelativeError( value, oldImplValue, relTol ); } -// TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION void testValuesAgainstPreviousImplementation( FlashModelBaseUpdate const & flashModelWrapper, - FlashModel const & oldFlashModel, - real64 const pressure, - real64 const temperature, + real64 const & pressure, + real64 const & temperature, arraySlice1d< real64 > const & compFraction, + real64 const & savedGasPhaseFrac, + real64 const & savedWaterPhaseGasComp, real64 const relTol ) { stackArray1d< real64, 2 > phaseFraction( 2 ); @@ -116,27 +97,23 @@ void testValuesAgainstPreviousImplementation( FlashModelBaseUpdate const & flash dPhaseCompFraction_dTemp, dPhaseCompFraction_dCompFraction ); - EvalVarArgs oldPres( pressure ); - EvalVarArgs oldTemp( temperature ); - stackArray1d< EvalVarArgs, 2 > oldCompFraction( 2 ); - stackArray1d< EvalVarArgs, 2 > oldPhaseFraction( 2 ); - stackArray2d< EvalVarArgs, 4 > oldPhaseCompFraction( 2, 2 ); - for( localIndex ic = 0; ic < 2; ic++ ) - { - oldCompFraction[ic].m_var = compFraction[ic]; - } - oldFlashModel.partition( oldPres, - oldTemp, - oldCompFraction, - oldPhaseFraction, - oldPhaseCompFraction ); - for( localIndex i = 0; i < 2; ++i ) { - checkRelativeError( phaseFraction[i], oldPhaseFraction[i].m_var, relTol ); + real64 const savedPhaseFrac = (i == 0) ? savedGasPhaseFrac : 1.0 - savedGasPhaseFrac; + checkRelativeError( phaseFraction[i], savedPhaseFrac, relTol ); + for( localIndex j = 0; j < 2; ++j ) { - checkRelativeError( phaseCompFraction[i][j], oldPhaseCompFraction[i][j].m_var, relTol ); + real64 savedCompFrac = 0.0; + if( i == 0 ) + { + savedCompFrac = ( j == 0 ) ? 1 : 0; + } + else + { + savedCompFrac = ( j == 0 ) ? savedWaterPhaseGasComp : 1 - savedWaterPhaseGasComp; + } + checkRelativeError( phaseCompFraction[i][j], savedCompFrac, relTol ); } } } @@ -434,7 +411,6 @@ class BrineViscosityTest : public ::testing::Test writeTableToFile( filename, pvtliquid_str ); pvtFunction = makePVTFunction< BrineViscosity >( filename, key ); - oldPvtFunction = makePVTFunction< BrineViscosityFunction >( filename, key ); // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION } virtual void TearDown() override @@ -446,7 +422,6 @@ class BrineViscosityTest : public ::testing::Test string const filename = "pvtliquid.txt"; std::unique_ptr< BrineViscosity > pvtFunction; - std::unique_ptr< BrineViscosityFunction > oldPvtFunction; // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION }; TEST_F( BrineViscosityTest, brineViscosityValuesAndDeriv ) @@ -454,21 +429,36 @@ TEST_F( BrineViscosityTest, brineViscosityValuesAndDeriv ) real64 const P[3] = { 5e6, 7.5e6, 1.2e7 }; real64 const TC[3] = { 94.5, 95, 95.6 }; array1d< real64 > comp( 2 ); - comp[0] = 0.3; comp[1] = 0.7; + comp[0] = 0.304; comp[1] = 0.696; + real64 const deltaComp = 0.2; real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); real64 const relTol = 5e-5; + real64 const savedValues[] = { 0.0009009475991, 0.0009009665224, 0.0009009892304, 0.0009009475991, 0.0009009665224, + 0.0009009892304, 0.0009009475991, 0.0009009665224, 0.0009009892304, 0.0009009475991, + 0.0009009665224, 0.0009009892304, 0.0009009475991, 0.0009009665224, 0.0009009892304, + 0.0009009475991, 0.0009009665224, 0.0009009892304, 0.0009009475991, 0.0009009665224, + 0.0009009892304, 0.0009009475991, 0.0009009665224, 0.0009009892304, 0.0009009475991, + 0.0009009665224, 0.0009009892304 }; + BrineViscosity::KernelWrapper pvtFunctionWrapper = pvtFunction->createKernelWrapper(); - for( localIndex iPres = 0; iPres < 3; ++iPres ) + localIndex counter = 0; + for( localIndex iComp = 0; iComp < 3; ++iComp ) { - for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + for( localIndex iPres = 0; iPres < 3; ++iPres ) { - testValuesAgainstPreviousImplementation( pvtFunctionWrapper, // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION - *oldPvtFunction, P[iPres], TC[iTemp], comp, true, relTol ); - testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, true, eps, relTol ); + for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + { + testValuesAgainstPreviousImplementation( pvtFunctionWrapper, + P[iPres], TC[iTemp], comp, savedValues[counter], true, relTol ); + testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, true, eps, relTol ); + counter++; + } } + comp[0] += deltaComp; + comp[1] = 1 - comp[0]; } } @@ -481,7 +471,6 @@ class FenghourCO2ViscosityTest : public ::testing::Test writeTableToFile( filename, pvtgas_str ); pvtFunction = makePVTFunction< FenghourCO2Viscosity >( filename, key ); - oldPvtFunction = makePVTFunction< FenghourCO2ViscosityFunction >( filename, key ); // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION } virtual void TearDown() override @@ -493,7 +482,6 @@ class FenghourCO2ViscosityTest : public ::testing::Test string const filename = "pvtgas.txt"; std::unique_ptr< FenghourCO2Viscosity > pvtFunction; - std::unique_ptr< FenghourCO2ViscosityFunction > oldPvtFunction; // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION }; TEST_F( FenghourCO2ViscosityTest, fenghourCO2ViscosityValuesAndDeriv ) @@ -503,21 +491,35 @@ TEST_F( FenghourCO2ViscosityTest, fenghourCO2ViscosityValuesAndDeriv ) real64 const P[3] = { 5.012e6, 7.546e6, 1.289e7 }; real64 const TC[3] = { 94.5, 95.1, 95.6 }; array1d< real64 > comp( 2 ); - comp[0] = 0.3; comp[1] = 0.7; + comp[0] = 0.304; comp[1] = 0.696; + real64 const deltaComp = 0.2; real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); real64 const relTol = 5e-5; + real64 const savedValues[] = { 1.904605302e-05, 1.907031467e-05, 1.909055363e-05, 2.008611673e-05, 2.010303796e-05, 2.011728461e-05, + 2.508888392e-05, 2.504245053e-05, 2.500575965e-05, 1.904605302e-05, 1.907031467e-05, 1.909055363e-05, + 2.008611673e-05, 2.010303796e-05, 2.011728461e-05, 2.508888392e-05, 2.504245053e-05, 2.500575965e-05, + 1.904605302e-05, 1.907031467e-05, 1.909055363e-05, 2.008611673e-05, 2.010303796e-05, 2.011728461e-05, + 2.508888392e-05, 2.504245053e-05, 2.500575965e-05 }; + FenghourCO2Viscosity::KernelWrapper pvtFunctionWrapper = pvtFunction->createKernelWrapper(); - for( localIndex iPres = 0; iPres < 3; ++iPres ) + localIndex counter = 0; + for( localIndex iComp = 0; iComp < 3; ++iComp ) { - for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + for( localIndex iPres = 0; iPres < 3; ++iPres ) { - testValuesAgainstPreviousImplementation( pvtFunctionWrapper, // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION - *oldPvtFunction, P[iPres], TC[iTemp], comp, true, relTol ); - testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, true, eps, relTol ); + for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + { + testValuesAgainstPreviousImplementation( pvtFunctionWrapper, + P[iPres], TC[iTemp], comp, savedValues[counter], true, relTol ); + testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, true, eps, relTol ); + counter++; + } } + comp[0] += deltaComp; + comp[1] = 1 - comp[0]; } } @@ -530,7 +532,6 @@ class BrineCO2DensityTest : public ::testing::Test writeTableToFile( filename, pvtliquid_str ); pvtFunction = makePVTFunction< BrineCO2Density >( filename, key ); - oldPvtFunction = makePVTFunction< BrineCO2DensityFunction >( filename, key ); // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION } virtual void TearDown() override @@ -542,7 +543,6 @@ class BrineCO2DensityTest : public ::testing::Test string const filename = "pvtliquid.txt"; std::unique_ptr< BrineCO2Density > pvtFunction; - std::unique_ptr< BrineCO2DensityFunction > oldPvtFunction; // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION }; TEST_F( BrineCO2DensityTest, brineCO2DensityMassValuesAndDeriv ) @@ -552,21 +552,34 @@ TEST_F( BrineCO2DensityTest, brineCO2DensityMassValuesAndDeriv ) real64 const P[3] = { 5.012e6, 7.546e6, 1.289e7 }; real64 const TC[3] = { 94.5, 95.1, 95.6 }; array1d< real64 > comp( 2 ); - comp[0] = 0.3; comp[1] = 0.7; + comp[0] = 0.304; comp[1] = 0.696; + real64 const deltaComp = 0.2; real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); real64 const relTol = 5e-5; + real64 const savedValues[] = { 1186.281618, 1185.321099, 1184.511961, 1186.997612, 1186.037426, 1185.228539, 1188.470081, 1187.510437, + 1186.70195, 1477.603717, 1476.040357, 1474.719028, 1476.803422, 1475.235146, 1473.909633, 1475.091089, + 1473.51237, 1472.177974, 2162.60433, 2159.623476, 2157.097807, 2158.238706, 2155.240595, 2152.700314, + 2149.037782, 2146.003403, 2143.432409 }; + BrineCO2Density::KernelWrapper pvtFunctionWrapper = pvtFunction->createKernelWrapper(); - for( localIndex iPres = 0; iPres < 3; ++iPres ) + localIndex counter = 0; + for( localIndex iComp = 0; iComp < 3; ++iComp ) { - for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + for( localIndex iPres = 0; iPres < 3; ++iPres ) { - testValuesAgainstPreviousImplementation( pvtFunctionWrapper, // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION - *oldPvtFunction, P[iPres], TC[iTemp], comp, true, relTol ); - testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, true, eps, relTol ); + for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + { + testValuesAgainstPreviousImplementation( pvtFunctionWrapper, + P[iPres], TC[iTemp], comp, savedValues[counter], true, relTol ); + testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, true, eps, relTol ); + counter++; + } } + comp[0] += deltaComp; + comp[1] = 1 - comp[0]; } } @@ -577,21 +590,37 @@ TEST_F( BrineCO2DensityTest, brineCO2DensityMolarValuesAndDeriv ) real64 const P[3] = { 5.012e6, 7.546e6, 1.289e7 }; real64 const TC[3] = { 94.5, 95.1, 95.6 }; array1d< real64 > comp( 2 ); - comp[0] = 0.3; comp[1] = 0.7; + comp[0] = 0.304; comp[1] = 0.696; + real64 const deltaComp = 0.2; real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); real64 const relTol = 5e-5; + // ======================================================================= + // TODO FRANCOIS: NEW AND OLD MODEL PRODUCE NEGATIVE MOLAR DENSITIES !!!! + // ======================================================================= + real64 const savedValues[] = { 32023.1563, 31987.53048, 31957.40422, 31997.76967, 31962.01198, 31931.77369, 31943.80393, + 31907.76711, 31877.29169, 3267.434571, 3221.843011, 3182.926776, 3071.375934, 3025.161549, 2985.719723, + 2660.391855, 2612.877907, 2572.339248, -64347.37057, -64416.39509, -64475.97965, -64944.73907, + -65015.54082, -65076.62339, -66195.19869, -66269.69941, -66333.90028 }; + BrineCO2Density::KernelWrapper pvtFunctionWrapper = pvtFunction->createKernelWrapper(); - for( localIndex iPres = 0; iPres < 3; ++iPres ) + localIndex counter = 0; + for( localIndex iComp = 0; iComp < 3; ++iComp ) { - for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + for( localIndex iPres = 0; iPres < 3; ++iPres ) { - testValuesAgainstPreviousImplementation( pvtFunctionWrapper, // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION - *oldPvtFunction, P[iPres], TC[iTemp], comp, false, relTol ); - testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, false, eps, relTol ); + for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + { + testValuesAgainstPreviousImplementation( pvtFunctionWrapper, + P[iPres], TC[iTemp], comp, savedValues[counter], false, relTol ); + testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, false, eps, relTol ); + counter++; + } } + comp[0] += deltaComp; + comp[1] = 1 - comp[0]; } } @@ -605,7 +634,6 @@ class SpanWagnerCO2DensityTest : public ::testing::Test writeTableToFile( filename, pvtgas_str ); pvtFunction = makePVTFunction< SpanWagnerCO2Density >( filename, key ); - oldPvtFunction = makePVTFunction< SpanWagnerCO2DensityFunction >( filename, key ); // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION } virtual void TearDown() override @@ -617,7 +645,6 @@ class SpanWagnerCO2DensityTest : public ::testing::Test string const filename = "pvtgas.txt"; std::unique_ptr< SpanWagnerCO2Density > pvtFunction; - std::unique_ptr< SpanWagnerCO2DensityFunction > oldPvtFunction; // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION }; TEST_F( SpanWagnerCO2DensityTest, spanWagnerCO2DensityMassValuesAndDeriv ) @@ -627,21 +654,34 @@ TEST_F( SpanWagnerCO2DensityTest, spanWagnerCO2DensityMassValuesAndDeriv ) real64 const P[3] = { 5.012e6, 7.546e6, 1.289e7 }; real64 const TC[3] = { 94.5, 95.1, 95.6 }; array1d< real64 > comp( 2 ); - comp[0] = 0.3; comp[1] = 0.7; + comp[0] = 0.304; comp[1] = 0.696; + real64 const deltaComp = 0.2; real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); real64 const relTol = 5e-5; + real64 const savedValues[] = { 82.78363562, 82.56888654, 82.39168811, 135.3774839, 134.9199659, 134.5440568, 281.9140962, 280.2559694, + 278.9092508, 82.78363562, 82.56888654, 82.39168811, 135.3774839, 134.9199659, 134.5440568, 281.9140962, + 280.2559694, 278.9092508, 82.78363562, 82.56888654, 82.39168811, 135.3774839, 134.9199659, 134.5440568, + 281.9140962, 280.2559694, 278.9092508 }; + SpanWagnerCO2Density::KernelWrapper pvtFunctionWrapper = pvtFunction->createKernelWrapper(); - for( localIndex iPres = 0; iPres < 3; ++iPres ) + localIndex counter = 0; + for( localIndex iComp = 0; iComp < 3; ++iComp ) { - for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + for( localIndex iPres = 0; iPres < 3; ++iPres ) { - testValuesAgainstPreviousImplementation( pvtFunctionWrapper, // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION - *oldPvtFunction, P[iPres], TC[iTemp], comp, true, relTol ); - testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, true, eps, relTol ); + for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + { + testValuesAgainstPreviousImplementation( pvtFunctionWrapper, + P[iPres], TC[iTemp], comp, savedValues[counter], true, relTol ); + testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, true, eps, relTol ); + counter++; + } } + comp[0] += deltaComp; + comp[1] = 1 - comp[0]; } } @@ -652,21 +692,34 @@ TEST_F( SpanWagnerCO2DensityTest, spanWagnerCO2DensityMolarValuesAndDeriv ) real64 const P[3] = { 5.012e6, 7.546e6, 1.289e7 }; real64 const TC[3] = { 94.5, 95.1, 95.6 }; array1d< real64 > comp( 2 ); - comp[0] = 0.3; comp[1] = 0.7; + comp[0] = 0.304; comp[1] = 0.696; + real64 const deltaComp = 0.2; real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); real64 const relTol = 5e-5; + real64 const savedValues[] = { 1881.446264, 1876.565603, 1872.538366, 3076.760999, 3066.362862, 3057.819473, 6407.138549, 6369.45385, + 6338.846609, 1881.446264, 1876.565603, 1872.538366, 3076.760999, 3066.362862, 3057.819473, 6407.138549, + 6369.45385, 6338.846609, 1881.446264, 1876.565603, 1872.538366, 3076.760999, 3066.362862, 3057.819473, + 6407.138549, 6369.45385, 6338.846609 }; + SpanWagnerCO2Density::KernelWrapper pvtFunctionWrapper = pvtFunction->createKernelWrapper(); - for( localIndex iPres = 0; iPres < 3; ++iPres ) + localIndex counter = 0; + for( localIndex iComp = 0; iComp < 3; ++iComp ) { - for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + for( localIndex iPres = 0; iPres < 3; ++iPres ) { - testValuesAgainstPreviousImplementation( pvtFunctionWrapper, // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION - *oldPvtFunction, P[iPres], TC[iTemp], comp, false, relTol ); - testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, false, eps, relTol ); + for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + { + testValuesAgainstPreviousImplementation( pvtFunctionWrapper, + P[iPres], TC[iTemp], comp, savedValues[counter], false, relTol ); + testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, false, eps, relTol ); + counter++; + } } + comp[0] += deltaComp; + comp[1] = 1 - comp[0]; } } @@ -680,7 +733,6 @@ class CO2SolubilityTest : public ::testing::Test writeTableToFile( filename, co2flash_str ); flashModel = makeFlashModel< CO2Solubility >( filename, key ); - oldFlashModel = makeFlashModel< CO2SolubilityFunction >( filename, key ); // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION } virtual void TearDown() override @@ -692,7 +744,6 @@ class CO2SolubilityTest : public ::testing::Test string const filename = "co2flash.txt"; std::unique_ptr< CO2Solubility > flashModel; - std::unique_ptr< CO2SolubilityFunction > oldFlashModel; // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION }; TEST_F( CO2SolubilityTest, co2SolubilityValuesAndDeriv ) @@ -702,21 +753,40 @@ TEST_F( CO2SolubilityTest, co2SolubilityValuesAndDeriv ) real64 const P[3] = { 5.012e6, 7.546e6, 1.289e7 }; real64 const TC[3] = { 94.5, 95.1, 95.6 }; array1d< real64 > comp( 2 ); - comp[0] = 0.3; comp[1] = 0.7; + comp[0] = 0.304; comp[1] = 0.696; + real64 const deltaComp = 0.2; real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); real64 const relTol = 5e-5; + real64 const savedGasPhaseFrac[] = { 0.298158785, 0.298183347, 0.2982033821, 0.295950309, 0.2959791448, 0.2960026365, 0.2926988393, + 0.292724834, 0.2927459702, 0.499837295, 0.499854799, 0.4998690769, 0.4982634386, 0.4982839883, + 0.4983007295, 0.4959462993, 0.4959648242, 0.4959798868, 0.7015158051, 0.701526251, 0.7015347717, + 0.7005765682, 0.7005888317, 0.7005988224, 0.6991937592, 0.6992048145, 0.6992138034 }; + real64 const savedWaterPhaseGasComp[] = { 0.008322701666, 0.008287995083, 0.008259683449, 0.01143341315, 0.0113929227, 0.01135993384, + 0.01597786252, 0.01594169644, 0.015912288, 0.008322701666, 0.008287995083, 0.008259683449, + 0.01143341315, 0.0113929227, 0.01135993384, 0.01597786252, 0.01594169644, 0.015912288, + 0.008322701666, 0.008287995083, 0.008259683449, 0.01143341315, 0.0113929227, 0.01135993384, + 0.01597786252, 0.01594169644, 0.015912288 }; + CO2Solubility::KernelWrapper flashModelWrapper = flashModel->createKernelWrapper(); - for( localIndex iPres = 0; iPres < 3; ++iPres ) + localIndex counter = 0; + for( localIndex iComp = 0; iComp < 3; ++iComp ) { - for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + for( localIndex iPres = 0; iPres < 3; ++iPres ) { - testValuesAgainstPreviousImplementation( flashModelWrapper, // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION - *oldFlashModel, P[iPres], TC[iTemp], comp, relTol ); - testNumericalDerivatives( flashModelWrapper, P[iPres], TC[iTemp], comp, eps, relTol ); + for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) + { + testValuesAgainstPreviousImplementation( flashModelWrapper, + P[iPres], TC[iTemp], comp, + savedGasPhaseFrac[counter], savedWaterPhaseGasComp[counter], relTol ); + testNumericalDerivatives( flashModelWrapper, P[iPres], TC[iTemp], comp, eps, relTol ); + counter++; + } } + comp[0] += deltaComp; + comp[1] = 1 - comp[0]; } } diff --git a/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp b/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp index 9564742ad76..cc3bcc542cc 100644 --- a/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp +++ b/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp @@ -281,12 +281,20 @@ void testNumericalDerivatives( MultiFluidBase & fluid, } ); } -// TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION -void testValuesAgainstPreviousImplementation( NewMultiPhaseMultiComponentFluid::KernelWrapper const & wrapper, - MultiPhaseMultiComponentFluid::KernelWrapper const & oldWrapper, +void testValuesAgainstPreviousImplementation( MultiPhaseMultiComponentFluid::KernelWrapper const & wrapper, real64 const P, real64 const T, arraySlice1d< real64 > const & composition, + real64 const & savedTotalDensity, + real64 const & savedGasPhaseFrac, + real64 const & savedWaterDens, + real64 const & savedGasDens, + real64 const & savedWaterMassDens, + real64 const & savedGasMassDens, + real64 const & savedWaterVisc, + real64 const & savedGasVisc, + real64 const & savedWaterPhaseGasComp, + real64 const & savedWaterPhaseWaterComp, real64 const relTol ) { stackArray1d< real64, 2 > phaseFraction( 2 ); @@ -314,13 +322,6 @@ void testValuesAgainstPreviousImplementation( NewMultiPhaseMultiComponentFluid:: real64 dTotalDensity_dTemperature = 0.0; stackArray1d< real64, 2 > dTotalDensity_dGlobalCompFraction( 2 ); - stackArray1d< real64, 2 > oldPhaseFraction( 2 ); - stackArray1d< real64, 2 > oldPhaseDensity( 2 ); - stackArray1d< real64, 2 > oldPhaseMassDensity( 2 ); - stackArray1d< real64, 2 > oldPhaseViscosity( 2 ); - stackArray2d< real64, 4 > oldPhaseCompFraction( 2, 2 ); - real64 oldTotalDensity = 0.0; - wrapper.compute( P, T, composition, phaseFraction, dPhaseFraction_dPressure, @@ -347,42 +348,29 @@ void testValuesAgainstPreviousImplementation( NewMultiPhaseMultiComponentFluid:: dTotalDensity_dTemperature, dTotalDensity_dGlobalCompFraction ); - oldWrapper.compute( P, T, composition, - oldPhaseFraction, - dPhaseFraction_dPressure, - dPhaseFraction_dTemperature, - dPhaseFraction_dGlobalCompFraction, - oldPhaseDensity, - dPhaseDensity_dPressure, - dPhaseDensity_dTemperature, - dPhaseDensity_dGlobalCompFraction, - oldPhaseMassDensity, - dPhaseMassDensity_dPressure, - dPhaseMassDensity_dTemperature, - dPhaseMassDensity_dGlobalCompFraction, - oldPhaseViscosity, - dPhaseViscosity_dPressure, - dPhaseViscosity_dTemperature, - dPhaseViscosity_dGlobalCompFraction, - oldPhaseCompFraction, - dPhaseCompFraction_dPressure, - dPhaseCompFraction_dTemperature, - dPhaseCompFraction_dGlobalCompFraction, - oldTotalDensity, - dTotalDensity_dPressure, - dTotalDensity_dTemperature, - dTotalDensity_dGlobalCompFraction ); - - checkRelativeError( totalDensity, oldTotalDensity, relTol ); + checkRelativeError( totalDensity, savedTotalDensity, relTol ); for( localIndex ip = 0; ip < 2; ++ip ) { - checkRelativeError( phaseFraction[ip], oldPhaseFraction[ip], relTol ); - checkRelativeError( phaseDensity[ip], oldPhaseDensity[ip], relTol ); - checkRelativeError( phaseMassDensity[ip], oldPhaseMassDensity[ip], relTol ); - checkRelativeError( phaseViscosity[ip], oldPhaseViscosity[ip], relTol ); + real64 const savedPhaseFrac = ( ip == 0 ) ? savedGasPhaseFrac : 1 - savedGasPhaseFrac; + checkRelativeError( phaseFraction[ip], savedPhaseFrac, relTol ); + real64 const savedPhaseDens = ( ip == 0 ) ? savedGasDens : savedWaterDens; + checkRelativeError( phaseDensity[ip], savedPhaseDens, relTol ); + real64 const savedPhaseMassDens = ( ip == 0 ) ? savedGasMassDens : savedWaterMassDens; + checkRelativeError( phaseMassDensity[ip], savedPhaseMassDens, relTol ); + real64 const savedPhaseVisc = ( ip == 0 ) ? savedGasVisc : savedWaterVisc; + checkRelativeError( phaseViscosity[ip], savedPhaseVisc, relTol ); for( localIndex ic = 0; ic < 2; ++ic ) { - checkRelativeError( phaseCompFraction[ip][ic], oldPhaseCompFraction[ip][ic], relTol ); + real64 savedCompFrac = 0.0; + if( ip == 0 ) + { + savedCompFrac = ( ic == 0 ) ? 1 : 0; + } + else + { + savedCompFrac = ( ic == 0 ) ? savedWaterPhaseGasComp : savedWaterPhaseWaterComp; + } + checkRelativeError( phaseCompFraction[ip][ic], savedCompFrac, relTol ); } } } @@ -680,34 +668,6 @@ TEST_F( DeadOilFluidTest, numericalDerivativesMass ) } MultiFluidBase & makeMultiPhaseMultiComponentFluid( string const & name, Group * parent ) -{ - NewMultiPhaseMultiComponentFluid & fluid = parent->registerGroup< NewMultiPhaseMultiComponentFluid >( name ); - - auto & compNames = fluid.getReference< string_array >( MultiFluidBase::viewKeyStruct::componentNamesString() ); - compNames.resize( 2 ); - compNames[0] = "co2"; compNames[1] = "water"; - - auto & molarWgt = fluid.getReference< array1d< real64 > >( MultiFluidBase::viewKeyStruct::componentMolarWeightString() ); - molarWgt.resize( 2 ); - molarWgt[0] = 44e-3; molarWgt[1] = 18e-3; - - auto & phaseNames = fluid.getReference< string_array >( MultiFluidBase::viewKeyStruct::phaseNamesString() ); - phaseNames.resize( 2 ); - phaseNames[0] = "gas"; phaseNames[1] = "liquid"; - - auto & phasePVTParaFileNames = fluid.getReference< path_array >( MultiPhaseMultiComponentFluid::viewKeyStruct::phasePVTParaFilesString() ); - phasePVTParaFileNames.resize( 2 ); - phasePVTParaFileNames[0] = "pvtgas.txt"; phasePVTParaFileNames[1] = "pvtliquid.txt"; - - auto & flashModelParaFileName = fluid.getReference< Path >( MultiPhaseMultiComponentFluid::viewKeyStruct::flashModelParaFileString() ); - flashModelParaFileName = "co2flash.txt"; - - fluid.postProcessInputRecursive(); - return fluid; -} - -// TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION -MultiFluidBase & makeOldMultiPhaseMultiComponentFluid( string const & name, Group * parent ) { MultiPhaseMultiComponentFluid & fluid = parent->registerGroup< MultiPhaseMultiComponentFluid >( name ); @@ -734,7 +694,6 @@ MultiFluidBase & makeOldMultiPhaseMultiComponentFluid( string const & name, Grou return fluid; } - class MultiPhaseMultiComponentFluidTest : public CompositionalFluidTestBase { protected: @@ -747,7 +706,6 @@ class MultiPhaseMultiComponentFluidTest : public CompositionalFluidTestBase parent.resize( 1 ); fluid = &makeMultiPhaseMultiComponentFluid( "fluid", &parent ); - oldFluid = &makeOldMultiPhaseMultiComponentFluid( "oldFluid", &parent ); parent.initialize(); parent.initializePostInitialConditions(); @@ -760,16 +718,13 @@ class MultiPhaseMultiComponentFluidTest : public CompositionalFluidTestBase removeFile( "co2flash.txt" ); } - MultiFluidBase * oldFluid; // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION }; // TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION -TEST_F( MultiPhaseMultiComponentFluidTest, checkAgainstPreviousImplementationMolarTemporary ) +TEST_F( MultiPhaseMultiComponentFluidTest, checkAgainstPreviousImplementationMolar ) { fluid->setMassFlag( false ); - oldFluid->setMassFlag( false ); - // TODO test over a range of values real64 const P[3] = { 5e6, 7.5e6, 1.2e7 }; real64 const T[3] = { 367.65, 368.15, 368.75 }; array1d< real64 > comp( 2 ); @@ -778,50 +733,120 @@ TEST_F( MultiPhaseMultiComponentFluidTest, checkAgainstPreviousImplementationMol real64 const relTol = 1e-10; fluid->allocateConstitutiveData( fluid->getParent(), 1 ); - oldFluid->allocateConstitutiveData( oldFluid->getParent(), 1 ); - - NewMultiPhaseMultiComponentFluid::KernelWrapper wrapper = - dynamicCast< NewMultiPhaseMultiComponentFluid * >( fluid )->createKernelWrapper(); - MultiPhaseMultiComponentFluid::KernelWrapper oldWrapper = - dynamicCast< MultiPhaseMultiComponentFluid * >( oldFluid )->createKernelWrapper(); + MultiPhaseMultiComponentFluid::KernelWrapper wrapper = + dynamicCast< MultiPhaseMultiComponentFluid * >( fluid )->createKernelWrapper(); + + real64 const savedTotalDens[] = + { 5881.8128183956969224, 5869.522096458530541, 5854.9469601674582009, 9180.9455320478591602, 9157.2045503913905122, 9129.1751063784995495, 15755.475565136142905, 15696.691553847707837, + 15627.990771463533747 }; + real64 const savedGasPhaseFrac[] = + { 0.29413690046142371148, 0.29415754810481165027, 0.29418169867697463449, 0.29194010802017489326, 0.29196434961986583723, 0.29199266189550621142, 0.2890641335638892695, 0.28908718137828937067, + 0.28911404840933618843 }; + real64 const savedWaterDens[] = + { 53286.457784368176362, 53264.389103437584708, 53237.751306267287873, 53229.257940878436784, 53207.597127679167897, 53181.436584967217641, 53197.49848403003125, 53176.033397316634364, + 53150.105086882285832 }; + real64 const savedGasDens[] = + { 1876.2436091302606656, 1872.184636376355229, 1867.3711104617746059, 3053.1548401973859654, 3044.5748249030266379, 3034.4507978134674886, 5769.0622621289458039, 5742.8476745352018042, + 5712.2837704249559465 }; + real64 const savedWaterMassDens[] = + { 970.85108546544745423, 970.4075834766143771, 969.87385780866463847, 974.23383396044232541, 973.78856424100911227, 973.25280170872576946, 979.48333010951580491, 979.04147229150635212, + 978.50977403260912979 }; + real64 const savedGasMassDens[] = + { 82.554718801731468147, 82.376124000559627802, 82.164328860318079251, 134.33881296868497657, 133.96129229573315911, 133.51583510379256836, 253.83873953367358922, 252.68529767954885301, + 251.34048589869803436 }; + real64 const savedWaterVisc[] = + { 0.00090094759910161340347, 0.00090096652240945261734, 0.00090098923037885969567, 0.00090094759910161340347, 0.00090096652240945261734, 0.00090098923037885969567, 0.00090094759910161340347, + 0.00090096652240945261734, 0.00090098923037885969567 }; + real64 const savedGasVisc[] = + { 1.9042384704865343673e-05, 1.9062615947696152414e-05, 1.9086923154230274463e-05, 2.0061713844617985449e-05, 2.0075955757102255573e-05, 2.0093249989250199265e-05, 2.3889596884008691474e-05, + 2.3865756080512667728e-05, 2.3839170076324036522e-05 }; + real64 const savedWaterPhaseGasComp[] = + { 0.0083062842389820552153, 0.008277274736736653718, 0.0082433415400525456018, 0.011383065290266058955, 0.011349217198060387521, 0.011309682362800700661, 0.015382352969377973903, + 0.015350431636424789056, 0.015313218057419366105 }; + real64 const savedWaterPhaseWaterComp[] = + { 0.99169371576101794652, 0.9917227252632633272, 0.99175665845994742664, 0.98861693470973388553, 0.98865078280193963156, 0.98869031763719927852, 0.98461764703062204518, 0.98464956836357520054, + 0.98468678194258063563 }; + + localIndex counter = 0; for( localIndex i = 0; i < 3; ++i ) { for( localIndex j = 0; j < 3; ++j ) { - testValuesAgainstPreviousImplementation( wrapper, oldWrapper, P[i], T[j], comp, relTol ); + testValuesAgainstPreviousImplementation( wrapper, + P[i], T[j], comp, + savedTotalDens[counter], savedGasPhaseFrac[counter], + savedWaterDens[counter], savedGasDens[counter], + savedWaterMassDens[counter], savedGasMassDens[counter], + savedWaterVisc[counter], savedGasVisc[counter], + savedWaterPhaseGasComp[counter], savedWaterPhaseWaterComp[counter], + relTol ); + counter++; } } } -// TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION -TEST_F( MultiPhaseMultiComponentFluidTest, checkAgainstPreviousImplementationMassTemporary ) +TEST_F( MultiPhaseMultiComponentFluidTest, checkAgainstPreviousImplementationMass ) { fluid->setMassFlag( true ); - oldFluid->setMassFlag( true ); - // TODO test over a range of values real64 const P[3] = { 5e6, 7.5e6, 1.2e7 }; real64 const T[3] = { 367.65, 368.15, 368.75 }; array1d< real64 > comp( 2 ); comp[0] = 0.3; comp[1] = 0.7; - //real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); real64 const relTol = 1e-10; fluid->allocateConstitutiveData( fluid->getParent(), 1 ); - oldFluid->allocateConstitutiveData( oldFluid->getParent(), 1 ); - - NewMultiPhaseMultiComponentFluid::KernelWrapper wrapper = - dynamicCast< NewMultiPhaseMultiComponentFluid * >( fluid )->createKernelWrapper(); - MultiPhaseMultiComponentFluid::KernelWrapper oldWrapper = - dynamicCast< MultiPhaseMultiComponentFluid * >( oldFluid )->createKernelWrapper(); + MultiPhaseMultiComponentFluid::KernelWrapper wrapper = + dynamicCast< MultiPhaseMultiComponentFluid * >( fluid )->createKernelWrapper(); + + real64 const savedTotalDens[] = + { 238.33977561940088208, 237.86350488026934613, 237.29874890241927687, 354.01144731214282046, 353.18618684355078585, 352.21120673560858449, 550.02182875764299297, 548.3889751707506548, + 546.47580480217254717 }; + real64 const savedGasPhaseFrac[] = + { 0.28562868803317220667, 0.28567941665326646028, 0.285738749802139258, 0.28022484140718162404, 0.2802844989853667812, 0.28035417162546172332, 0.2731355646393489045, 0.27319238868618361815, + 0.2732586251114847431 }; + real64 const savedWaterDens[] = + { 970.85108546544745423, 970.4075834766143771, 969.87385780866463847, 974.23383396044232541, 973.78856424100911227, 973.25280170872576946, 979.48333010951580491, 979.04147229150635212, + 978.50977403260912979 }; + real64 const savedGasDens[] = + { 82.554718801731468147, 82.376124000559627802, 82.164328860318079251, 134.33881296868497657, 133.96129229573315911, 133.51583510379256836, 253.83873953367358922, 252.68529767954885301, + 251.34048589869803436 }; + real64 const savedWaterMassDens[] = + { 970.85108546544745423, 970.4075834766143771, 969.87385780866463847, 974.23383396044232541, 973.78856424100911227, 973.25280170872576946, 979.48333010951580491, 979.04147229150635212, + 978.50977403260912979 }; + real64 const savedGasMassDens[] = + { 82.554718801731468147, 82.376124000559627802, 82.164328860318079251, 134.33881296868497657, 133.96129229573315911, 133.51583510379256836, 253.83873953367358922, 252.68529767954885301, + 251.34048589869803436 }; + real64 const savedWaterVisc[] = + { 0.00090094759910161340347, 0.00090096652240945261734, 0.00090098923037885969567, 0.00090094759910161340347, 0.00090096652240945261734, 0.00090098923037885969567, 0.00090094759910161340347, + 0.00090096652240945261734, 0.00090098923037885969567 }; + real64 const savedGasVisc[] = + { 1.9042384704865343673e-05, 1.9062615947696152414e-05, 1.9086923154230274463e-05, 2.0061713844617985449e-05, 2.0075955757102255573e-05, 2.0093249989250199265e-05, 2.3889596884008691474e-05, + 2.3865756080512667728e-05, 2.3839170076324036522e-05 }; + real64 const savedWaterPhaseGasComp[] = + { 0.02005966592318779787, 0.019990461277537684842, 0.019909503061226688919, 0.027365230280837819082, 0.027285226317914228894, 0.027191770514265831832, 0.036759501299346700187, + 0.036684965747010883641, 0.036598063202886929601 }; + real64 const savedWaterPhaseWaterComp[] = + { 0.9797478006656266114, 0.97981828292617156873, 0.97990072673671935188, 0.97227194517798976037, 0.97235397979974458327, 0.97244979317916002692, 0.9625743441996873484, 0.9626514061444874093, + 0.962741233539301966 }; + + localIndex counter = 0; for( localIndex i = 0; i < 3; ++i ) { for( localIndex j = 0; j < 3; ++j ) { - testValuesAgainstPreviousImplementation( wrapper, oldWrapper, P[i], T[j], comp, relTol ); + testValuesAgainstPreviousImplementation( wrapper, + P[i], T[j], comp, + savedTotalDens[counter], savedGasPhaseFrac[counter], + savedWaterDens[counter], savedGasDens[counter], + savedWaterMassDens[counter], savedGasMassDens[counter], + savedWaterVisc[counter], savedGasVisc[counter], + savedWaterPhaseGasComp[counter], savedWaterPhaseWaterComp[counter], + relTol ); + counter++; } } } diff --git a/src/coreComponents/fileIO/schema/docs/Constitutive.rst b/src/coreComponents/fileIO/schema/docs/Constitutive.rst index 78abed327b9..911789f350c 100644 --- a/src/coreComponents/fileIO/schema/docs/Constitutive.rst +++ b/src/coreComponents/fileIO/schema/docs/Constitutive.rst @@ -19,7 +19,6 @@ ElasticIsotropic node :ref:`XML_ElasticIsotropic` ElasticTransverseIsotropic node :ref:`XML_ElasticTransverseIsotropic` ExtendedDruckerPrager node :ref:`XML_ExtendedDruckerPrager` MultiPhaseMultiComponentFluid node :ref:`XML_MultiPhaseMultiComponentFluid` -NewMultiPhaseMultiComponentFluid node :ref:`XML_NewMultiPhaseMultiComponentFluid` NullModel node :ref:`XML_NullModel` ParticleFluid node :ref:`XML_ParticleFluid` PoreVolumeCompressibleSolid node :ref:`XML_PoreVolumeCompressibleSolid` diff --git a/src/coreComponents/fileIO/schema/docs/Constitutive_other.rst b/src/coreComponents/fileIO/schema/docs/Constitutive_other.rst index a9f863b3711..c92dca56db8 100644 --- a/src/coreComponents/fileIO/schema/docs/Constitutive_other.rst +++ b/src/coreComponents/fileIO/schema/docs/Constitutive_other.rst @@ -19,7 +19,6 @@ ElasticIsotropic node :ref:`DATASTRUCTURE_ElasticIsotropic` ElasticTransverseIsotropic node :ref:`DATASTRUCTURE_ElasticTransverseIsotropic` ExtendedDruckerPrager node :ref:`DATASTRUCTURE_ExtendedDruckerPrager` MultiPhaseMultiComponentFluid node :ref:`DATASTRUCTURE_MultiPhaseMultiComponentFluid` -NewMultiPhaseMultiComponentFluid node :ref:`DATASTRUCTURE_NewMultiPhaseMultiComponentFluid` NullModel node :ref:`DATASTRUCTURE_NullModel` ParticleFluid node :ref:`DATASTRUCTURE_ParticleFluid` PoreVolumeCompressibleSolid node :ref:`DATASTRUCTURE_PoreVolumeCompressibleSolid` diff --git a/src/coreComponents/fileIO/schema/docs/MultiPhaseMultiComponentFluid.rst b/src/coreComponents/fileIO/schema/docs/MultiPhaseMultiComponentFluid.rst index 941214d016f..2010eb6efc8 100644 --- a/src/coreComponents/fileIO/schema/docs/MultiPhaseMultiComponentFluid.rst +++ b/src/coreComponents/fileIO/schema/docs/MultiPhaseMultiComponentFluid.rst @@ -1,14 +1,14 @@ -==================== ============ ======== ================================================================= -Name Type Default Description -==================== ============ ======== ================================================================= -componentMolarWeight real64_array {0} Component molar weights -componentNames string_array {} List of component names -flashModelParaFile path required name of the filen including flash calculation function parameters -name string required A name is required for any non-unique nodes -phaseNames string_array {} List of fluid phases -phasePVTParaFiles path_array required List of the names of the files including PVT function parameters -==================== ============ ======== ================================================================= +==================== ============ ======== ============================================================================== +Name Type Default Description +==================== ============ ======== ============================================================================== +componentMolarWeight real64_array {0} Component molar weights +componentNames string_array {} List of component names +flashModelParaFile path required Name of the file defining the parameters of the flash model +name string required A name is required for any non-unique nodes +phaseNames string_array {} List of fluid phases +phasePVTParaFiles path_array required Names of the files defining the parameters of the viscosity and density models +==================== ============ ======== ============================================================================== diff --git a/src/coreComponents/fileIO/schema/schema.xsd b/src/coreComponents/fileIO/schema/schema.xsd index 18e94f05478..739f13306b0 100644 --- a/src/coreComponents/fileIO/schema/schema.xsd +++ b/src/coreComponents/fileIO/schema/schema.xsd @@ -1625,7 +1625,6 @@ Equal to 1 for surface conditions, and to 0 for reservoir conditions--> - @@ -1928,20 +1927,6 @@ The expected format is "{ waterMax, oilMax }", in that order--> - - - - - - - - - - - - - - diff --git a/src/coreComponents/fileIO/schema/schema.xsd.other b/src/coreComponents/fileIO/schema/schema.xsd.other index c0c9a9e713e..ed16d722796 100644 --- a/src/coreComponents/fileIO/schema/schema.xsd.other +++ b/src/coreComponents/fileIO/schema/schema.xsd.other @@ -700,7 +700,6 @@ - @@ -1052,58 +1051,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp index ba14e94b517..7451ce61813 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp @@ -388,15 +388,16 @@ void CompositionalMultiphaseBase::updateFluidModel( Group & dataGroup, localInde constitutive::constitutiveUpdatePassThru( fluid, [&] ( auto & castedFluid ) { - typename TYPEOFREF( castedFluid ) ::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); - - // MultiFluid models are not thread-safe or device-capable yet - FluidUpdateKernel::launch< serialPolicy >( dataGroup.size(), - fluidWrapper, - pres, - dPres, - m_temperature, - compFrac ); + using FluidType = TYPEOFREF( castedFluid ); + using ExecPolicy = typename FluidType::exec_policy; + typename FluidType::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); + + FluidUpdateKernel::launch< ExecPolicy >( dataGroup.size(), + fluidWrapper, + pres, + dPres, + m_temperature, + compFrac ); } ); } @@ -891,10 +892,10 @@ void CompositionalMultiphaseBase::applyDirichletBC( real64 const time, bcStatusMap[subRegionName][setName].setValues< serialPolicy >( false ); // 1.1. Apply BC to set the field values - fs.applyFieldValue< FieldSpecificationEqual, parallelHostPolicy >( targetSet, - time + dt, - subRegion, - viewKeyStruct::bcPressureString() ); + fs.applyFieldValue< FieldSpecificationEqual, parallelDevicePolicy<> >( targetSet, + time + dt, + subRegion, + viewKeyStruct::bcPressureString() ); } ); // 2. Apply composition BC (global component fraction) and store them for constitutive call @@ -918,10 +919,10 @@ void CompositionalMultiphaseBase::applyDirichletBC( real64 const time, bcStatusMap[subRegionName][setName][comp] = true; // 2.1. Apply BC to set the field values - fs.applyFieldValue< FieldSpecificationEqual, parallelHostPolicy >( targetSet, - time + dt, - subRegion, - viewKeyStruct::globalCompFractionString() ); + fs.applyFieldValue< FieldSpecificationEqual, parallelDevicePolicy<> >( targetSet, + time + dt, + subRegion, + viewKeyStruct::globalCompFractionString() ); } ); // 2.3 Check consistency between composition BC applied to sets @@ -973,14 +974,15 @@ void CompositionalMultiphaseBase::applyDirichletBC( real64 const time, constitutiveUpdatePassThru( fluid, [&] ( auto & castedFluid ) { - typename TYPEOFREF( castedFluid ) ::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); - - // MultiFluid models are not thread-safe or device-capable yet - FluidUpdateKernel::launch< serialPolicy >( targetSet, - fluidWrapper, - bcPres, - m_temperature, - compFrac ); + using FluidType = TYPEOFREF( castedFluid ); + using ExecPolicy = typename FluidType::exec_policy; + typename FluidType::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); + + FluidUpdateKernel::launch< ExecPolicy >( targetSet, + fluidWrapper, + bcPres, + m_temperature, + compFrac ); } ); forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOSX_HOST_DEVICE ( localIndex const a ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBaseKernels.hpp index 1b0e8fcab00..c385c83bfa7 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBaseKernels.hpp @@ -134,7 +134,7 @@ struct FluidUpdateKernel real64 const temp, arrayView2d< real64 const > const & compFrac ) { - forAll< POLICY >( size, [=] ( localIndex const k ) + forAll< POLICY >( size, [=] GEOSX_HOST_DEVICE ( localIndex const k ) { for( localIndex q = 0; q < fluidWrapper.numGauss(); ++q ) { @@ -152,7 +152,7 @@ struct FluidUpdateKernel real64 const temp, arrayView2d< real64 const > const & compFrac ) { - forAll< POLICY >( size, [=] ( localIndex const k ) + forAll< POLICY >( size, [=] GEOSX_HOST_DEVICE ( localIndex const k ) { for( localIndex q = 0; q < fluidWrapper.numGauss(); ++q ) { @@ -170,7 +170,7 @@ struct FluidUpdateKernel real64 const temp, arrayView2d< real64 const > const & compFrac ) { - forAll< POLICY >( targetSet.size(), [=] ( localIndex const a ) + forAll< POLICY >( targetSet.size(), [=] GEOSX_HOST_DEVICE ( localIndex const a ) { localIndex const k = targetSet[a]; for( localIndex q = 0; q < fluidWrapper.numGauss(); ++q ) @@ -188,7 +188,7 @@ struct FluidUpdateKernel real64 const temp, arrayView2d< real64 const > const & compFrac ) { - forAll< POLICY >( targetSet.size(), [=] ( localIndex const a ) + forAll< POLICY >( targetSet.size(), [=] GEOSX_HOST_DEVICE ( localIndex const a ) { localIndex const k = targetSet[a]; for( localIndex q = 0; q < fluidWrapper.numGauss(); ++q ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.cpp index b249b4a5c91..047af023645 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.cpp @@ -110,30 +110,32 @@ void CompositionalMultiphaseFVM::assembleFluxTerms( real64 const dt, * Or stop testing through the solver interface and test separate kernels instead. * Finally, the problem should go away when fluid updates are executed on device. */ - forTargetSubRegions( mesh, [&]( localIndex const targetIndex, ElementSubRegionBase const & subRegion ) - { - MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidModelNames()[targetIndex] ); - arrayView4d< real64 const > const & phaseCompFrac = fluid.phaseCompFraction(); - arrayView4d< real64 const > const & dPhaseCompFrac_dPres = fluid.dPhaseCompFraction_dPressure(); - arrayView5d< real64 const > const & dPhaseCompFrac_dComp = fluid.dPhaseCompFraction_dGlobalCompFraction(); - - arrayView3d< real64 const > const & phaseMassDens = fluid.phaseMassDensity(); - arrayView3d< real64 const > const & dPhaseMassDens_dPres = fluid.dPhaseMassDensity_dPressure(); - arrayView4d< real64 const > const & dPhaseMassDens_dComp = fluid.dPhaseMassDensity_dGlobalCompFraction(); - - forAll< parallelDevicePolicy<> >( subRegion.size(), + /* + forTargetSubRegions( mesh, [&]( localIndex const targetIndex, ElementSubRegionBase const & subRegion ) + { + MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidModelNames()[targetIndex] ); + arrayView4d< real64 const > const & phaseCompFrac = fluid.phaseCompFraction(); + arrayView4d< real64 const > const & dPhaseCompFrac_dPres = fluid.dPhaseCompFraction_dPressure(); + arrayView5d< real64 const > const & dPhaseCompFrac_dComp = fluid.dPhaseCompFraction_dGlobalCompFraction(); + + arrayView3d< real64 const > const & phaseMassDens = fluid.phaseMassDensity(); + arrayView3d< real64 const > const & dPhaseMassDens_dPres = fluid.dPhaseMassDensity_dPressure(); + arrayView4d< real64 const > const & dPhaseMassDens_dComp = fluid.dPhaseMassDensity_dGlobalCompFraction(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [phaseCompFrac, dPhaseCompFrac_dPres, dPhaseCompFrac_dComp, phaseMassDens, dPhaseMassDens_dPres, dPhaseMassDens_dComp] GEOSX_HOST_DEVICE ( localIndex const ) - { + { GEOSX_UNUSED_VAR( phaseCompFrac ) GEOSX_UNUSED_VAR( dPhaseCompFrac_dPres ) GEOSX_UNUSED_VAR( dPhaseCompFrac_dComp ) GEOSX_UNUSED_VAR( phaseMassDens ) GEOSX_UNUSED_VAR( dPhaseMassDens_dPres ) GEOSX_UNUSED_VAR( dPhaseMassDens_dComp ) - } ); - } ); + } ); + } ); + */ NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 26c230ba649..0f687cbae8a 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -690,14 +690,16 @@ void CompositionalMultiphaseWell::updateFluidModel( WellElementSubRegion & subRe constitutive::constitutiveUpdatePassThru( fluid, [&] ( auto & castedFluid ) { - typename TYPEOFREF( castedFluid ) ::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); - - CompositionalMultiphaseBaseKernels::FluidUpdateKernel::launch< serialPolicy >( subRegion.size(), - fluidWrapper, - pres, - dPres, - m_temperature, - compFrac ); + using FluidType = TYPEOFREF( castedFluid ); + using ExecPolicy = typename FluidType::exec_policy; + typename FluidType::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); + + CompositionalMultiphaseBaseKernels::FluidUpdateKernel::launch< ExecPolicy >( subRegion.size(), + fluidWrapper, + pres, + dPres, + m_temperature, + compFrac ); } ); } diff --git a/src/docs/sphinx/CompleteXMLSchema.rst b/src/docs/sphinx/CompleteXMLSchema.rst index 8e8ead21999..e061b304d34 100644 --- a/src/docs/sphinx/CompleteXMLSchema.rst +++ b/src/docs/sphinx/CompleteXMLSchema.rst @@ -372,13 +372,6 @@ Element: MultiPhaseMultiComponentFluid .. include:: ../../coreComponents/fileIO/schema/docs/MultiPhaseMultiComponentFluid.rst -.. _XML_NewMultiPhaseMultiComponentFluid: - -Element: NewMultiPhaseMultiComponentFluid -========================================= -.. include:: ../../coreComponents/fileIO/schema/docs/NewMultiPhaseMultiComponentFluid.rst - - .. _XML_NonlinearSolverParameters: Element: NonlinearSolverParameters @@ -1153,13 +1146,6 @@ Datastructure: MultiPhaseMultiComponentFluid .. include:: ../../coreComponents/fileIO/schema/docs/MultiPhaseMultiComponentFluid_other.rst -.. _DATASTRUCTURE_NewMultiPhaseMultiComponentFluid: - -Datastructure: NewMultiPhaseMultiComponentFluid -=============================================== -.. include:: ../../coreComponents/fileIO/schema/docs/NewMultiPhaseMultiComponentFluid_other.rst - - .. _DATASTRUCTURE_NonlinearSolverParameters: Datastructure: NonlinearSolverParameters From 9de00b7dca91be9ce746c8ed9875fbd79c43a8bc Mon Sep 17 00:00:00 2001 From: Francois Hamon Date: Fri, 26 Feb 2021 16:02:00 -0800 Subject: [PATCH 03/10] remove outdated rst to make sure all CI tests pass --- .../docs/NewMultiPhaseMultiComponentFluid.rst | 14 -------- ...NewMultiPhaseMultiComponentFluid_other.rst | 33 ------------------- 2 files changed, 47 deletions(-) delete mode 100644 src/coreComponents/fileIO/schema/docs/NewMultiPhaseMultiComponentFluid.rst delete mode 100644 src/coreComponents/fileIO/schema/docs/NewMultiPhaseMultiComponentFluid_other.rst diff --git a/src/coreComponents/fileIO/schema/docs/NewMultiPhaseMultiComponentFluid.rst b/src/coreComponents/fileIO/schema/docs/NewMultiPhaseMultiComponentFluid.rst deleted file mode 100644 index 2010eb6efc8..00000000000 --- a/src/coreComponents/fileIO/schema/docs/NewMultiPhaseMultiComponentFluid.rst +++ /dev/null @@ -1,14 +0,0 @@ - - -==================== ============ ======== ============================================================================== -Name Type Default Description -==================== ============ ======== ============================================================================== -componentMolarWeight real64_array {0} Component molar weights -componentNames string_array {} List of component names -flashModelParaFile path required Name of the file defining the parameters of the flash model -name string required A name is required for any non-unique nodes -phaseNames string_array {} List of fluid phases -phasePVTParaFiles path_array required Names of the files defining the parameters of the viscosity and density models -==================== ============ ======== ============================================================================== - - diff --git a/src/coreComponents/fileIO/schema/docs/NewMultiPhaseMultiComponentFluid_other.rst b/src/coreComponents/fileIO/schema/docs/NewMultiPhaseMultiComponentFluid_other.rst deleted file mode 100644 index 5b3d3c27bb3..00000000000 --- a/src/coreComponents/fileIO/schema/docs/NewMultiPhaseMultiComponentFluid_other.rst +++ /dev/null @@ -1,33 +0,0 @@ - - -====================================== ============================================================================================== ========================== -Name Type Description -====================================== ============================================================================================== ========================== -dPhaseCompFraction_dGlobalCompFraction LvArray_Array< double, 5, camp_int_seq< long, 0l, 1l, 2l, 3l, 4l >, long, LvArray_ChaiBuffer > (no description available) -dPhaseCompFraction_dPressure LvArray_Array< double, 4, camp_int_seq< long, 0l, 1l, 2l, 3l >, long, LvArray_ChaiBuffer > (no description available) -dPhaseCompFraction_dTemperature LvArray_Array< double, 4, camp_int_seq< long, 0l, 1l, 2l, 3l >, long, LvArray_ChaiBuffer > (no description available) -dPhaseDensity_dGlobalCompFraction LvArray_Array< double, 4, camp_int_seq< long, 0l, 1l, 2l, 3l >, long, LvArray_ChaiBuffer > (no description available) -dPhaseDensity_dPressure real64_array3d (no description available) -dPhaseDensity_dTemperature real64_array3d (no description available) -dPhaseFraction_dGlobalCompFraction LvArray_Array< double, 4, camp_int_seq< long, 0l, 1l, 2l, 3l >, long, LvArray_ChaiBuffer > (no description available) -dPhaseFraction_dPressure real64_array3d (no description available) -dPhaseFraction_dTemperature real64_array3d (no description available) -dPhaseMassDensity_dGlobalCompFraction LvArray_Array< double, 4, camp_int_seq< long, 0l, 1l, 2l, 3l >, long, LvArray_ChaiBuffer > (no description available) -dPhaseMassDensity_dPressure real64_array3d (no description available) -dPhaseMassDensity_dTemperature real64_array3d (no description available) -dPhaseViscosity_dGlobalCompFraction LvArray_Array< double, 4, camp_int_seq< long, 0l, 1l, 2l, 3l >, long, LvArray_ChaiBuffer > (no description available) -dPhaseViscosity_dPressure real64_array3d (no description available) -dPhaseViscosity_dTemperature real64_array3d (no description available) -dTotalDensity_dGlobalCompFraction real64_array3d (no description available) -dTotalDensity_dPressure real64_array2d (no description available) -dTotalDensity_dTemperature real64_array2d (no description available) -phaseCompFraction LvArray_Array< double, 4, camp_int_seq< long, 0l, 1l, 2l, 3l >, long, LvArray_ChaiBuffer > (no description available) -phaseDensity real64_array3d (no description available) -phaseFraction real64_array3d (no description available) -phaseMassDensity real64_array3d (no description available) -phaseViscosity real64_array3d (no description available) -totalDensity real64_array2d (no description available) -useMass integer (no description available) -====================================== ============================================================================================== ========================== - - From 601518c9f532cf501af890f79fcab6f104fcd5a5 Mon Sep 17 00:00:00 2001 From: Francois Hamon Date: Wed, 10 Mar 2021 13:53:14 -0800 Subject: [PATCH 04/10] addressed Thomas' comments --- .../constitutive/CMakeLists.txt | 1 + .../fluid/MultiPhaseMultiComponentFluid.cpp | 50 +++-- .../fluid/MultiPhaseMultiComponentFluid.hpp | 10 +- .../PVTFunctions/BrineCO2DensityFunction.cpp | 53 +++--- .../PVTFunctions/BrineCO2DensityFunction.hpp | 7 +- .../PVTFunctions/BrineViscosityFunction.cpp | 7 +- .../PVTFunctions/BrineViscosityFunction.hpp | 7 +- .../PVTFunctions/CO2SolubilityFunction.cpp | 96 ++++------ .../PVTFunctions/CO2SolubilityFunction.hpp | 5 + .../FenghourCO2ViscosityFunction.cpp | 16 +- .../FenghourCO2ViscosityFunction.hpp | 7 +- .../fluid/PVTFunctions/FlashModelBase.hpp | 11 +- .../fluid/PVTFunctions/PVTFunctionBase.hpp | 13 +- .../fluid/PVTFunctions/PVTFunctionHelpers.hpp | 71 +++++++ .../SpanWagnerCO2DensityFunction.cpp | 35 ++-- .../SpanWagnerCO2DensityFunction.hpp | 5 + .../unitTests/testCO2BrinePVTModels.cpp | 2 +- .../constitutive/unitTests/testMultiFluid.cpp | 175 +++++++++--------- 18 files changed, 322 insertions(+), 249 deletions(-) create mode 100644 src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp diff --git a/src/coreComponents/constitutive/CMakeLists.txt b/src/coreComponents/constitutive/CMakeLists.txt index 23f491c3fbb..c9b687e6b99 100644 --- a/src/coreComponents/constitutive/CMakeLists.txt +++ b/src/coreComponents/constitutive/CMakeLists.txt @@ -22,6 +22,7 @@ set( constitutive_headers fluid/PVTFunctions/FlashModelBase.hpp fluid/PVTFunctions/PVTFunctionBase.hpp fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp + fluid/PVTFunctions/PVTFunctionHelpers.hpp fluid/SingleFluidBase.hpp fluid/singleFluidSelector.hpp fluid/MultiFluidBase.hpp diff --git a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp index f229e1a464e..c31962240be 100644 --- a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp +++ b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp @@ -19,18 +19,20 @@ #include "common/Path.hpp" #include "constitutive/fluid/MultiFluidUtils.hpp" -#include "PVTFunctions/FlashModelBase.hpp" -#include "PVTFunctions/PVTFunctionBase.hpp" +#include "constitutive/fluid/PVTFunctions/FlashModelBase.hpp" +#include "constitutive/fluid/PVTFunctions/PVTFunctionBase.hpp" +#include "constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp" namespace geosx { using namespace dataRepository; -using namespace PVTProps; namespace constitutive { +using namespace PVTProps; + MultiPhaseMultiComponentFluid::MultiPhaseMultiComponentFluid( string const & name, Group * const parent ): MultiFluidBase( name, parent ) { @@ -74,31 +76,23 @@ void MultiPhaseMultiComponentFluid::postProcessInput() GEOSX_ERROR_IF( numComps != 2, "The number of components in this model should be equal to 2" ); GEOSX_ERROR_IF( m_phasePVTParaFiles.size() != 2, "The number of phasePVTParaFiles is not the same as the number of phases!" ); - bool notFound = true; - for( localIndex i = 0; i < m_phaseNames.size(); ++i ) - { - if( m_phaseNames[i] == "CO2" || m_phaseNames[i] == "co2" || - m_phaseNames[i] == "gas" || m_phaseNames[i] == "Gas" ) - { - m_phaseGasIndex = i; - notFound = false; - break; - } - } - GEOSX_ERROR_IF( notFound, "Phase co2/gas is not found!" ); - - notFound = true; - for( localIndex i = 0; i < m_phaseNames.size(); ++i ) - { - if( m_phaseNames[i] == "Water" || m_phaseNames[i] == "water" || - m_phaseNames[i] == "Liquid" || m_phaseNames[i] == "liquid" ) - { - m_phaseLiquidIndex = i; - notFound = false; - break; - } - } - GEOSX_ERROR_IF( notFound, "Phase water/liquid is not found!" ); + array1d< string > expectedGasPhaseNames; + expectedGasPhaseNames.resize( 4 ); + expectedGasPhaseNames[0] = "CO2"; + expectedGasPhaseNames[1] = "co2"; + expectedGasPhaseNames[2] = "gas"; + expectedGasPhaseNames[3] = "Gas"; + bool found = PVTFunctionHelpers::findName( m_phaseNames, expectedGasPhaseNames, m_phaseGasIndex ); + GEOSX_ERROR_IF( !found, "Phase co2/gas is not found!" ); + + array1d< string > expectedWaterPhaseNames; + expectedWaterPhaseNames.resize( 4 ); + expectedWaterPhaseNames[0] = "Water"; + expectedWaterPhaseNames[1] = "water"; + expectedWaterPhaseNames[2] = "Liquid"; + expectedWaterPhaseNames[3] = "liquid"; + found = PVTFunctionHelpers::findName( m_phaseNames, expectedWaterPhaseNames, m_phaseLiquidIndex ); + GEOSX_ERROR_IF( !found, "Phase water/liquid is not found!" ); createPVTModels(); } diff --git a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp index 212eb20eaa0..d0f228344a4 100644 --- a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp +++ b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp @@ -21,11 +21,11 @@ #include "constitutive/fluid/MultiFluidBase.hpp" #include "constitutive/fluid/MultiFluidUtils.hpp" -#include "PVTFunctions/BrineCO2DensityFunction.hpp" -#include "PVTFunctions/SpanWagnerCO2DensityFunction.hpp" -#include "PVTFunctions/BrineViscosityFunction.hpp" -#include "PVTFunctions/FenghourCO2ViscosityFunction.hpp" -#include "PVTFunctions/CO2SolubilityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp" #include diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp index 657c6c1f67d..a2bc7c50abc 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp @@ -13,11 +13,12 @@ */ /** - * @file BrineCO2Density.cpp + * @file BrineCO2DensityFunction.cpp */ #include "constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp" #include "managers/Functions/FunctionManager.hpp" #include "managers/GeosxState.hpp" @@ -26,6 +27,9 @@ namespace geosx using namespace stringutilities; +namespace constitutive +{ + namespace PVTProps { @@ -36,29 +40,19 @@ BrineCO2Density::BrineCO2Density( array1d< string > const & inputPara, componentNames, componentMolarWeight ) { - bool notFound = true; - for( localIndex i = 0; i < componentNames.size(); ++i ) - { - if( componentNames[i] == "CO2" || componentNames[i] == "co2" ) - { - m_CO2Index = i; - notFound = false; - break; - } - } - GEOSX_ERROR_IF( notFound, "Component CO2 is not found!" ); - - notFound = true; - for( localIndex i = 0; i < componentNames.size(); ++i ) - { - if( componentNames[i] =="Water" || componentNames[i] == "water" ) - { - m_waterIndex = i; - notFound = false; - break; - } - } - GEOSX_ERROR_IF( notFound, "Component Water/Brine is not found!" ); + array1d< string > expectedCO2ComponentNames; + expectedCO2ComponentNames.resize( 2 ); + expectedCO2ComponentNames[0] = "CO2"; + expectedCO2ComponentNames[1] = "co2"; + bool found = PVTFunctionHelpers::findName( componentNames, expectedCO2ComponentNames, m_CO2Index ); + GEOSX_ERROR_IF( !found, "Component CO2 is not found!" ); + + array1d< string > expectedWaterComponentNames; + expectedWaterComponentNames.resize( 2 ); + expectedWaterComponentNames[0] = "Water"; + expectedWaterComponentNames[1] = "water"; + found = PVTFunctionHelpers::findName( componentNames, expectedWaterComponentNames, m_waterIndex ); + GEOSX_ERROR_IF( !found, "Component Water/Brine is not found!" ); makeTable( inputPara ); } @@ -95,18 +89,13 @@ void BrineCO2Density::makeTable( array1d< string > const & inputPara ) GEOSX_ERROR( "Invalid BrineCO2Density argument:" + string( e.what()) ); } - real64 P = PStart; - while( P <= PEnd ) + for( real64 P = PStart; P <= PEnd; P += dP ) { coordinates[0].emplace_back( P ); - P += dP; } - - real64 T = TStart; - while( T <= TEnd ) + for( real64 T = TStart; T <= TEnd; T += dT ) { coordinates[1].emplace_back( T ); - T += dT; } localIndex const nP = coordinates[0].size(); @@ -172,4 +161,6 @@ REGISTER_CATALOG_ENTRY( PVTFunctionBase, BrineCO2Density, array1d< string > cons } // namespace PVTProps +} // namespace constitutive + } // namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp index 072f2c10dc0..591c357149b 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp @@ -13,7 +13,7 @@ */ /** - * @file BrineCO2Density.hpp + * @file BrineCO2DensityFunction.hpp */ #ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINECO2DENSITY_HPP_ @@ -26,6 +26,9 @@ namespace geosx { +namespace constitutive +{ + namespace PVTProps { @@ -224,6 +227,8 @@ void BrineCO2DensityUpdate::compute( real64 const & pressure, } // end namespace PVTProps +} // end namespace constitutive + } // end namespace geosx #endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINECO2DENSITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.cpp index e3046a34ece..92fdbc551dc 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.cpp @@ -13,7 +13,7 @@ */ /** - * @file BrineViscosity.cpp + * @file BrineViscosityFunction.cpp */ #include "constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp" @@ -23,6 +23,9 @@ namespace geosx using namespace stringutilities; +namespace constitutive +{ + namespace PVTProps { @@ -75,4 +78,6 @@ REGISTER_CATALOG_ENTRY( PVTFunctionBase, BrineViscosity, array1d< string > const } // end namespace PVTProps +} // namespace constitutive + } // end namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp index d7aa3351996..e7d3ba63933 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp @@ -13,7 +13,7 @@ */ /** - * @file BrineViscosity.hpp + * @file BrineViscosityFunction.hpp */ #ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINEVISCOSITY_HPP_ @@ -24,6 +24,9 @@ namespace geosx { +namespace constitutive +{ + namespace PVTProps { @@ -137,6 +140,8 @@ void BrineViscosityUpdate::compute( real64 const & pressure, } // end namespace PVTProps +} // end namespace constitutive + } // end namespace geosx #endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINEVISCOSITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp index ed040ef0da3..028e1ab26e2 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp @@ -13,11 +13,12 @@ */ /** - * @file CO2Solubility.cpp + * @file CO2SolubilityFunction.cpp */ #include "constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp" #include "managers/Functions/FunctionManager.hpp" #include "managers/GeosxState.hpp" @@ -26,6 +27,8 @@ namespace geosx using namespace stringutilities; +namespace constitutive +{ namespace PVTProps { @@ -136,55 +139,37 @@ CO2Solubility::CO2Solubility( array1d< string > const & inputPara, GEOSX_ERROR_IF( phaseNames.size() != 2, "The CO2Solubility model is a two-phase model" ); GEOSX_ERROR_IF( componentNames.size() != 2, "The CO2Solubility model is a two-component model" ); - bool notFound = true; - for( localIndex i = 0; i < componentNames.size(); ++i ) - { - if( componentNames[i] == "CO2" || componentNames[i] == "co2" ) - { - m_CO2Index = i; - notFound = false; - break; - } - } - GEOSX_ERROR_IF( notFound, "Component CO2 is not found!" ); - - notFound = true; - for( localIndex i = 0; i < componentNames.size(); ++i ) - { - if( componentNames[i] == "Water" || componentNames[i] == "water" ) - { - m_waterIndex = i; - notFound = false; - break; - } - } - GEOSX_ERROR_IF( notFound, "Component Water/Brine is not found!" ); - - notFound = true; - for( localIndex i = 0; i < phaseNames.size(); ++i ) - { - if( phaseNames[i] == "CO2" || phaseNames[i] == "co2" || - phaseNames[i] == "gas" || phaseNames[i] == "Gas" ) - { - m_phaseGasIndex = i; - notFound = false; - break; - } - } - GEOSX_ERROR_IF( notFound, "Phase co2/gas is not found!" ); - - notFound = true; - for( localIndex i = 0; i < phaseNames.size(); ++i ) - { - if( phaseNames[i] == "Water" || phaseNames[i] == "water" || - phaseNames[i] == "Liquid" || phaseNames[i] == "liquid" ) - { - m_phaseLiquidIndex = i; - notFound = false; - break; - } - } - GEOSX_ERROR_IF( notFound, "Phase water/liquid is not found!" ); + array1d< string > expectedCO2ComponentNames; + expectedCO2ComponentNames.resize( 2 ); + expectedCO2ComponentNames[0] = "CO2"; + expectedCO2ComponentNames[1] = "co2"; + bool found = PVTFunctionHelpers::findName( componentNames, expectedCO2ComponentNames, m_CO2Index ); + GEOSX_ERROR_IF( !found, "Component CO2 is not found!" ); + + array1d< string > expectedWaterComponentNames; + expectedWaterComponentNames.resize( 2 ); + expectedWaterComponentNames[0] = "Water"; + expectedWaterComponentNames[1] = "water"; + found = PVTFunctionHelpers::findName( componentNames, expectedWaterComponentNames, m_waterIndex ); + GEOSX_ERROR_IF( !found, "Component Water/Brine is not found!" ); + + array1d< string > expectedGasPhaseNames; + expectedGasPhaseNames.resize( 4 ); + expectedGasPhaseNames[0] = "CO2"; + expectedGasPhaseNames[1] = "co2"; + expectedGasPhaseNames[2] = "gas"; + expectedGasPhaseNames[3] = "Gas"; + found = PVTFunctionHelpers::findName( phaseNames, expectedGasPhaseNames, m_phaseGasIndex ); + GEOSX_ERROR_IF( !found, "Phase co2/gas is not found!" ); + + array1d< string > expectedWaterPhaseNames; + expectedWaterPhaseNames.resize( 4 ); + expectedWaterPhaseNames[0] = "Water"; + expectedWaterPhaseNames[1] = "water"; + expectedWaterPhaseNames[2] = "Liquid"; + expectedWaterPhaseNames[3] = "liquid"; + found = PVTFunctionHelpers::findName( phaseNames, expectedWaterPhaseNames, m_phaseLiquidIndex ); + GEOSX_ERROR_IF( !found, "Phase water/liquid is not found!" ); makeTable( inputPara ); } @@ -221,18 +206,13 @@ void CO2Solubility::makeTable( array1d< string > const & inputPara ) GEOSX_ERROR( "Invalid CO2Solubility argument:" + string( e.what()) ); } - real64 P = PStart; - while( P <= PEnd ) + for( real64 P = PStart; P <= PEnd; P += dP ) { coordinates[0].emplace_back( P ); - P += dP; } - - real64 T = TStart; - while( T <= TEnd ) + for( real64 T = TStart; T <= TEnd; T += dT ) { coordinates[1].emplace_back( T ); - T += dT; } localIndex const nP = coordinates[0].size(); @@ -341,4 +321,6 @@ REGISTER_CATALOG_ENTRY( FlashModelBase, CO2Solubility, array1d< string > const & } // end namespace PVTProps +} // namespace constitutive + } // end namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp index 147d6fb9ac5..bf05146f60b 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp @@ -26,6 +26,9 @@ namespace geosx { +namespace constitutive +{ + namespace PVTProps { @@ -293,6 +296,8 @@ void CO2SolubilityUpdate::compute( real64 const & pressure, } // end namespace PVTProps +} // end namespace constitutive + } // end namespace geosx #endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_CO2SOLUBILITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp index 6cdc4b37e99..2f3f27cd8bc 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp @@ -13,7 +13,7 @@ */ /** - * @file FenghourCO2Viscosity.cpp + * @file FenghourCO2ViscosityFunction.cpp */ #include "constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp" @@ -25,6 +25,9 @@ namespace geosx { +namespace constitutive +{ + namespace PVTProps { @@ -67,18 +70,13 @@ void FenghourCO2Viscosity::makeTable( array1d< string > const & inputPara ) GEOSX_ERROR( "Invalid FenghourCO2Viscosity argument:" + string( e.what()) ); } - real64 P = PStart; - while( P <= PEnd ) + for( real64 P = PStart; P <= PEnd; P += dP ) { coordinates[0].emplace_back( P ); - P += dP; } - - real64 T = TStart; - while( T <= TEnd ) + for( real64 T = TStart; T <= TEnd; T += dT ) { coordinates[1].emplace_back( T ); - T += dT; } localIndex nP = coordinates[0].size(); @@ -161,4 +159,6 @@ REGISTER_CATALOG_ENTRY( PVTFunctionBase, FenghourCO2Viscosity, array1d< string > } // end namespace PVTProps +} // namespace constitutive + } // end namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp index dace097df5c..056ff0542ac 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp @@ -13,7 +13,7 @@ */ /** - * @file FenghourCO2Viscosity.hpp + * @file FenghourCO2ViscosityFunction.hpp */ #ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FENGHOURCO2VISCOSITY_HPP_ @@ -26,6 +26,9 @@ namespace geosx { +namespace constitutive +{ + namespace PVTProps { @@ -143,6 +146,8 @@ void FenghourCO2ViscosityUpdate::compute( real64 const & pressure, } // end namespace PVTProps +} // end namespace constitutive + } // end namespace geosx #endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FENGHOURCO2VISCOSITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/FlashModelBase.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/FlashModelBase.hpp index 149be2c4136..4e3df8dedf1 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/FlashModelBase.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/FlashModelBase.hpp @@ -16,8 +16,8 @@ * @file FlashModelBase.hpp */ -#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWFLASHMODELBASE_HPP_ -#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWFLASHMODELBASE_HPP_ +#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FLASHMODELBASE_HPP_ +#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FLASHMODELBASE_HPP_ #include "codingUtilities/StringUtilities.hpp" #include "dataRepository/ObjectCatalog.hpp" @@ -25,6 +25,9 @@ namespace geosx { +namespace constitutive +{ + namespace PVTProps { @@ -121,6 +124,8 @@ class FlashModelBase } // end namespace PVTProps +} // end namespace constitutive + } // end namespace geosx -#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWFLASHMODELBASE_HPP_ +#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FLASHMODELBASE_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionBase.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionBase.hpp index 5e8c442f0a8..c6b9bfa5670 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionBase.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionBase.hpp @@ -13,11 +13,11 @@ */ /** - * @file NewPVTFunctionBase.hpp + * @file PVTFunctionBase.hpp */ -#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWPVTFUNCTIONBASE_HPP_ -#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWPVTFUNCTIONBASE_HPP_ +#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_PVTFUNCTIONBASE_HPP_ +#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_PVTFUNCTIONBASE_HPP_ #include "codingUtilities/StringUtilities.hpp" #include "dataRepository/ObjectCatalog.hpp" @@ -25,6 +25,9 @@ namespace geosx { +namespace constitutive +{ + namespace PVTProps { @@ -121,6 +124,8 @@ class PVTFunctionBase } // end namespace PVTProps +} // end namespace constitutive + } // end namespace geosx -#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_NEWPVTFUNCTIONBASE_HPP_ +#endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_PVTFUNCTIONBASE_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp new file mode 100644 index 00000000000..e28a1ac7d25 --- /dev/null +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp @@ -0,0 +1,71 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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 Total, S.A + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file PVTFunctionHelpers.hpp + */ + +#ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_PVTFUNCTIONHELPERS_HPP +#define GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_PVTFUNCTIONHELPERS_HPP + +namespace geosx +{ + +namespace constitutive +{ + +namespace PVTProps +{ + +struct PVTFunctionHelpers +{ + + /** + * @brief Look for the expectedNames in the names provided by the user + * @param[in] inputNames phase or component names provided by the user + * @param[in] expectedNames expected names that can be accepted by GEOSX + * @param[inout] id the index of the phase or component that was found + * @return true is an expectedName was found in the inputNames, false otherwise + */ + static bool + findName( array1d< string > const & inputNames, + array1d< string > const & expectedNames, + localIndex & id ) + { + id = -1; + for( localIndex i = 0; i < inputNames.size(); ++i ) + { + string const input = inputNames[i]; + for( localIndex j = 0; j < expectedNames.size(); ++j ) + { + if( input == expectedNames[j] ) + { + id = i; + return true; + } + } + } + return false; + } + +}; + +} // namespace PVTProps + +} // namespace constitutive + +} // namespace geosx + + +#endif diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp index 93e2abf1fd1..8d0881ed1cc 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp @@ -13,11 +13,12 @@ */ /** - * @file SpanWagnerCO2Density.cpp + * @file SpanWagnerCO2DensityFunction.cpp */ #include "constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp" #include "managers/Functions/FunctionManager.hpp" #include "managers/GeosxState.hpp" @@ -26,6 +27,9 @@ namespace geosx using namespace stringutilities; +namespace constitutive +{ + namespace PVTProps { @@ -143,18 +147,12 @@ SpanWagnerCO2Density::SpanWagnerCO2Density( array1d< string > const & inputPara, componentNames, componentMolarWeight ) { - - bool notFound = true; - for( localIndex i = 0; i < componentNames.size(); ++i ) - { - if( componentNames[i] == "CO2" || componentNames[i] == "co2" ) - { - m_CO2Index = i; - notFound = false; - break; - } - } - GEOSX_ERROR_IF( notFound, "Component CO2 is not found!" ); + array1d< string > expectedCO2ComponentNames; + expectedCO2ComponentNames.resize( 2 ); + expectedCO2ComponentNames[0] = "CO2"; + expectedCO2ComponentNames[1] = "co2"; + bool found = PVTFunctionHelpers::findName( componentNames, expectedCO2ComponentNames, m_CO2Index ); + GEOSX_ERROR_IF( !found, "Component CO2 is not found!" ); makeTable( inputPara ); } @@ -188,18 +186,13 @@ void SpanWagnerCO2Density::makeTable( array1d< string > const & inputPara ) GEOSX_ERROR( "Invalid SpanWagnerCO2Density argument:" + string( e.what()) ); } - real64 P = PStart; - while( P <= PEnd ) + for( real64 P = PStart; P <= PEnd; P += dP ) { coordinates[0].emplace_back( P ); - P += dP; } - - real64 T = TStart; - while( T <= TEnd ) + for( real64 T = TStart; T <= TEnd; T += dT ) { coordinates[1].emplace_back( T ); - T += dT; } localIndex const nP = coordinates[0].size(); @@ -318,4 +311,6 @@ REGISTER_CATALOG_ENTRY( PVTFunctionBase, SpanWagnerCO2Density, array1d< string > } // namespace PVTProps +} // namespace constitutive + } // namespace geosx diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp index c41aa07a216..c35155709c2 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp @@ -26,6 +26,9 @@ namespace geosx { +namespace constitutive +{ + namespace PVTProps { @@ -160,6 +163,8 @@ void SpanWagnerCO2DensityUpdate::compute( real64 const & pressure, } // end namespace PVTProps +} // end namespace constitutive + } // end namespace geosx #endif //GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_SPANWAGNERCO2DENSITY_HPP_ diff --git a/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp b/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp index 308f796ce1a..0fda2b86d90 100644 --- a/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp +++ b/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp @@ -33,7 +33,7 @@ using namespace geosx::testing; using namespace geosx::constitutive; using namespace geosx::dataRepository; using namespace geosx::stringutilities; -using namespace geosx::PVTProps; +using namespace geosx::constitutive::PVTProps; /// Input tables written into temporary files during testing diff --git a/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp b/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp index 13e37feae3b..01f6b8a3ea1 100644 --- a/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp +++ b/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp @@ -31,95 +31,95 @@ using namespace geosx; using namespace geosx::testing; using namespace geosx::constitutive; using namespace geosx::dataRepository; -using namespace geosx::PVTProps; +using namespace geosx::constitutive::PVTProps; /// Black-oil tables written into temporary files during testing -static const char * pvtg_str = "#\tPg(Pa)\t\tRv(sm3/sm3)\tBg(m3/sm3)\tVisc(Pa.s)\n" - "\n" - "\t3000000\t\t0.000132\t0.04234\t 0.00001344\n" - "\t\t\t\t0\t\t\t0.04231\t 0.00001389\n" - "\t6000000\t\t0.000124\t0.02046\t 0.0000142\n" - "\t\t\t\t0\t\t\t0.02043\t 0.0000145\n" - "\t9000000\t\t0.000126\t0.01328\t 0.00001526\n" - "\t\t\t\t0\t\t\t0.01325\t 0.00001532\n" - " 12000000\t\t0.000135\t0.00977\t 0.0000166\n" - "\t\t\t\t0\t\t\t0.00973\t 0.00001634\n" - " 15000000\t\t0.000149\t0.00773\t 0.00001818\n" - "\t\t\t\t0\t\t\t0.00769\t 0.00001752\n" - " 18000000\t\t0.000163\t0.006426\t0.00001994\n" - "\t\t\t\t0\t\t\t0.006405\t0.00001883\n" - " 21000000\t\t0.000191\t0.005541\t0.00002181\n" - "\t\t\t\t0\t\t\t0.005553\t0.00002021\n" - " 24000000\t\t0.000225\t0.004919\t0.0000237\n" - "\t\t\t\t0\t\t\t0.004952\t0.00002163\n" - " 27000000\t\t0.000272\t0.004471\t0.00002559\n" - "\t\t\t\t0\t\t\t0.004511\t0.00002305\n" - " 29500000\t\t0.000354\t0.004194\t0.00002714\n" - "\t\t\t\t0\t\t\t0.004225\t0.00002423\n" - " 31000000\t\t0.000403\t0.004031\t0.00002806\n" - "\t\t\t\t0.000354\t0.004059\t0.00002768\n" - " 33000000\t\t0.000354\t0.00391\t 0.00002832\n" - "\t\t\t\t0\t\t\t0.003913\t0.00002583\n" - " 53000000\t\t0.000479\t0.003868\t0.00002935\n" - "\t\t\t\t0.000354\t0.0039\t\t0.00002842\n" - "\t\t\t\t0\t\t\t0.003903\t0.00002593"; - -static const char * pvto_str = "# Rs[sm3/sm3]\tPbub[Pa]\tBo[m3/sm3]\tVisc(Pa.s)\n" - "\n" - " 2\t 2000000\t 1.02\t 0.000975\n" - " 5\t 5000000\t 1.03\t 0.00091\n" - " 10\t 10000000\t1.04\t 0.00083\n" - " 15\t 20000000\t1.05\t 0.000695\n" - " 90000000\t1.03\t 0.000985 -- some line comment\n" - " 30\t 30000000\t1.07\t 0.000594\n" - " 40\t 40000000\t1.08\t 0.00051\n" - " 50000000\t1.07\t 0.000549 -- another one\n" - " 90000000\t1.06\t 0.00074\n" - " 50\t 50000000.7\t1.09\t 0.000449\n" - " 90000000.7\t1.08\t 0.000605"; - -static const char * pvtw_str = "#\tPref[bar]\tBw[m3/sm3]\tCp[1/bar]\t Visc[cP]\n" - "\t30600000.1\t1.03\t\t0.00000000041\t0.0003"; +static const char * PVTGString = "#\tPg(Pa)\t\tRv(sm3/sm3)\tBg(m3/sm3)\tVisc(Pa.s)\n" + "\n" + "\t3000000\t\t0.000132\t0.04234\t 0.00001344\n" + "\t\t\t\t0\t\t\t0.04231\t 0.00001389\n" + "\t6000000\t\t0.000124\t0.02046\t 0.0000142\n" + "\t\t\t\t0\t\t\t0.02043\t 0.0000145\n" + "\t9000000\t\t0.000126\t0.01328\t 0.00001526\n" + "\t\t\t\t0\t\t\t0.01325\t 0.00001532\n" + " 12000000\t\t0.000135\t0.00977\t 0.0000166\n" + "\t\t\t\t0\t\t\t0.00973\t 0.00001634\n" + " 15000000\t\t0.000149\t0.00773\t 0.00001818\n" + "\t\t\t\t0\t\t\t0.00769\t 0.00001752\n" + " 18000000\t\t0.000163\t0.006426\t0.00001994\n" + "\t\t\t\t0\t\t\t0.006405\t0.00001883\n" + " 21000000\t\t0.000191\t0.005541\t0.00002181\n" + "\t\t\t\t0\t\t\t0.005553\t0.00002021\n" + " 24000000\t\t0.000225\t0.004919\t0.0000237\n" + "\t\t\t\t0\t\t\t0.004952\t0.00002163\n" + " 27000000\t\t0.000272\t0.004471\t0.00002559\n" + "\t\t\t\t0\t\t\t0.004511\t0.00002305\n" + " 29500000\t\t0.000354\t0.004194\t0.00002714\n" + "\t\t\t\t0\t\t\t0.004225\t0.00002423\n" + " 31000000\t\t0.000403\t0.004031\t0.00002806\n" + "\t\t\t\t0.000354\t0.004059\t0.00002768\n" + " 33000000\t\t0.000354\t0.00391\t 0.00002832\n" + "\t\t\t\t0\t\t\t0.003913\t0.00002583\n" + " 53000000\t\t0.000479\t0.003868\t0.00002935\n" + "\t\t\t\t0.000354\t0.0039\t\t0.00002842\n" + "\t\t\t\t0\t\t\t0.003903\t0.00002593"; + +static const char * PVTOString = "# Rs[sm3/sm3]\tPbub[Pa]\tBo[m3/sm3]\tVisc(Pa.s)\n" + "\n" + " 2\t 2000000\t 1.02\t 0.000975\n" + " 5\t 5000000\t 1.03\t 0.00091\n" + " 10\t 10000000\t1.04\t 0.00083\n" + " 15\t 20000000\t1.05\t 0.000695\n" + " 90000000\t1.03\t 0.000985 -- some line comment\n" + " 30\t 30000000\t1.07\t 0.000594\n" + " 40\t 40000000\t1.08\t 0.00051\n" + " 50000000\t1.07\t 0.000549 -- another one\n" + " 90000000\t1.06\t 0.00074\n" + " 50\t 50000000.7\t1.09\t 0.000449\n" + " 90000000.7\t1.08\t 0.000605"; + +static const char * PVTWString = "#\tPref[bar]\tBw[m3/sm3]\tCp[1/bar]\t Visc[cP]\n" + "\t30600000.1\t1.03\t\t0.00000000041\t0.0003"; /// Dead-oil tables written into temporary files during testing -static const char * pvdg_str = "# Pg(Pa) Bg(m3/sm3) Visc(Pa.s)\n" - "3000000 0.04234 0.00001344\n" - "6000000 0.02046 0.0000142\n" - "9000000 0.01328 0.00001526\n" - "12000000 0.00977 0.0000166\n" - "15000000 0.00773 0.00001818\n" - "18000000 0.006426 0.00001994\n" - "21000000 0.005541 0.00002181\n" - "24000000 0.004919 0.0000237\n" - "27000000 0.004471 0.00002559\n" - "29500000 0.004194 0.00002714\n" - "31000000 0.004031 0.00002806\n" - "33000000 0.00391 0.00002832\n" - "53000000 0.003868 0.00002935"; - -static const char * pvdo_str = "#P[Pa] Bo[m3/sm3] Visc(Pa.s)\n" - "2000000 1.02 0.000975\n" - "5000000 1.03 0.00091\n" - "10000000 1.04 0.00083\n" - "20000000 1.05 0.000695\n" - "30000000 1.07 0.000594\n" - "40000000 1.08 0.00051\n" - "50000000.7 1.09 0.000449"; - -static const char * pvdw_str = "# Pref[bar] Bw[m3/sm3] Cp[1/bar] Visc[cP]\n" - " 30600000.1 1.03 0.00000000041 0.0003"; +static const char * PVDGString = "# Pg(Pa) Bg(m3/sm3) Visc(Pa.s)\n" + "3000000 0.04234 0.00001344\n" + "6000000 0.02046 0.0000142\n" + "9000000 0.01328 0.00001526\n" + "12000000 0.00977 0.0000166\n" + "15000000 0.00773 0.00001818\n" + "18000000 0.006426 0.00001994\n" + "21000000 0.005541 0.00002181\n" + "24000000 0.004919 0.0000237\n" + "27000000 0.004471 0.00002559\n" + "29500000 0.004194 0.00002714\n" + "31000000 0.004031 0.00002806\n" + "33000000 0.00391 0.00002832\n" + "53000000 0.003868 0.00002935"; + +static const char * PVDOString = "#P[Pa] Bo[m3/sm3] Visc(Pa.s)\n" + "2000000 1.02 0.000975\n" + "5000000 1.03 0.00091\n" + "10000000 1.04 0.00083\n" + "20000000 1.05 0.000695\n" + "30000000 1.07 0.000594\n" + "40000000 1.08 0.00051\n" + "50000000.7 1.09 0.000449"; + +static const char * PVDWString = "# Pref[bar] Bw[m3/sm3] Cp[1/bar] Visc[cP]\n" + " 30600000.1 1.03 0.00000000041 0.0003"; // CO2-brine model -static const char * pvtliquid_str = "DensityFun BrineCO2Density 1e6 1.5e7 5e4 94 96 1 0.2\n" - "ViscosityFun BrineViscosity 0.1"; +static const char * PVTLiquidString = "DensityFun BrineCO2Density 1e6 1.5e7 5e4 94 96 1 0.2\n" + "ViscosityFun BrineViscosity 0.1"; -static const char * pvtgas_str = "DensityFun SpanWagnerCO2Density 1e6 1.5e7 5e4 94 96 1\n" - "ViscosityFun FenghourCO2Viscosity 1e6 1.5e7 5e4 94 96 1"; +static const char * PVTGasString = "DensityFun SpanWagnerCO2Density 1e6 1.5e7 5e4 94 96 1\n" + "ViscosityFun FenghourCO2Viscosity 1e6 1.5e7 5e4 94 96 1"; -static const char * co2flash_str = "FlashModel CO2Solubility 1e6 1.5e7 5e4 94 96 1 0.15"; +static const char * CO2FlashString = "FlashModel CO2Solubility 1e6 1.5e7 5e4 94 96 1 0.15"; void testNumericalDerivatives( MultiFluidBase & fluid, Group & parent, @@ -221,7 +221,6 @@ void testNumericalDerivatives( MultiFluidBase & fluid, "Pres", phases, components ); - std::cout << phaseDens.value << std::endl; } // update temperature and check derivatives @@ -657,9 +656,9 @@ class LiveOilFluidTest : public CompositionalFluidTestBase public: LiveOilFluidTest() { - writeTableToFile( "pvto.txt", pvto_str ); - writeTableToFile( "pvtg.txt", pvtg_str ); - writeTableToFile( "pvtw.txt", pvtw_str ); + writeTableToFile( "pvto.txt", PVTOString ); + writeTableToFile( "pvtg.txt", PVTGString ); + writeTableToFile( "pvtw.txt", PVTWString ); parent.resize( 1 ); fluid = &makeLiveOilFluid( "fluid", &parent ); @@ -715,9 +714,9 @@ class DeadOilFluidTest : public CompositionalFluidTestBase DeadOilFluidTest() { - writeTableToFile( "pvdo.txt", pvdo_str ); - writeTableToFile( "pvdg.txt", pvdg_str ); - writeTableToFile( "pvdw.txt", pvdw_str ); + writeTableToFile( "pvdo.txt", PVDOString ); + writeTableToFile( "pvdg.txt", PVDGString ); + writeTableToFile( "pvdw.txt", PVDWString ); parent.resize( 1 ); fluid = &makeDeadOilFluid( "fluid", &parent ); @@ -836,9 +835,9 @@ class MultiPhaseMultiComponentFluidTest : public CompositionalFluidTestBase MultiPhaseMultiComponentFluidTest() { - writeTableToFile( "pvtliquid.txt", pvtliquid_str ); - writeTableToFile( "pvtgas.txt", pvtgas_str ); - writeTableToFile( "co2flash.txt", co2flash_str ); + writeTableToFile( "pvtliquid.txt", PVTLiquidString ); + writeTableToFile( "pvtgas.txt", PVTGasString ); + writeTableToFile( "co2flash.txt", CO2FlashString ); parent.resize( 1 ); fluid = &makeMultiPhaseMultiComponentFluid( "fluid", &parent ); From 0c489b262db7da805c43439da199eaa7ef7aca63 Mon Sep 17 00:00:00 2001 From: Francois Hamon Date: Wed, 10 Mar 2021 18:07:52 -0800 Subject: [PATCH 05/10] addressed Sergey's and Thomas' comments --- .../fluid/MultiFluidPVTPackageWrapper.cpp | 8 +- .../fluid/MultiFluidPVTPackageWrapper.hpp | 4 +- .../fluid/MultiPhaseMultiComponentFluid.cpp | 28 ++--- .../fluid/MultiPhaseMultiComponentFluid.hpp | 105 ++++++++++-------- .../PVTFunctions/BrineCO2DensityFunction.cpp | 37 +++--- .../PVTFunctions/CO2SolubilityFunction.cpp | 66 +++++------ .../FenghourCO2ViscosityFunction.cpp | 19 ++-- .../fluid/PVTFunctions/PVTFunctionHelpers.hpp | 48 ++++---- .../SpanWagnerCO2DensityFunction.cpp | 25 ++--- 9 files changed, 163 insertions(+), 177 deletions(-) diff --git a/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.cpp b/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.cpp index 3e9a1f077c5..27b241380c9 100644 --- a/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.cpp +++ b/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.cpp @@ -92,7 +92,9 @@ void MultiFluidPVTPackageWrapperUpdate::compute( real64 pressure, arraySlice2d< real64 > const & phaseCompFrac, real64 & totalDens ) const { -#ifndef __CUDACC__ +#ifdef __CUDACC__ + GEOSX_ERROR( "This function cannot be used on GPU" ); +#else localIndex const NC = m_componentMolarWeight.size(); localIndex const NP = m_phaseTypes.size(); @@ -229,7 +231,9 @@ void MultiFluidPVTPackageWrapperUpdate::compute( real64 pressure, real64 & dTotalDensity_dTemperature, arraySlice1d< real64 > const & dTotalDensity_dGlobalCompFraction ) const { -#ifndef __CUDACC__ +#ifdef __CUDACC__ + GEOSX_ERROR( "This function cannot be used on GPU" ); +#else // 0. make shortcut structs to avoid long names (TODO maybe remove) CompositionalVarContainer< 1 > phaseFrac{ phaseFraction, diff --git a/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.hpp b/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.hpp index 6708fc77ede..27444505100 100644 --- a/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.hpp +++ b/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.hpp @@ -165,7 +165,9 @@ class MultiFluidPVTPackageWrapperUpdate final : public MultiFluidBaseUpdate real64 const temperature, arraySlice1d< real64 const > const & composition ) const override { -#ifndef __CUDACC__ +#ifdef __CUDACC__ + GEOSX_ERROR( "This function cannot be used on GPU" ); +#else compute( pressure, temperature, composition, diff --git a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp index c31962240be..34b2188d9a6 100644 --- a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp +++ b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp @@ -76,23 +76,17 @@ void MultiPhaseMultiComponentFluid::postProcessInput() GEOSX_ERROR_IF( numComps != 2, "The number of components in this model should be equal to 2" ); GEOSX_ERROR_IF( m_phasePVTParaFiles.size() != 2, "The number of phasePVTParaFiles is not the same as the number of phases!" ); - array1d< string > expectedGasPhaseNames; - expectedGasPhaseNames.resize( 4 ); - expectedGasPhaseNames[0] = "CO2"; - expectedGasPhaseNames[1] = "co2"; - expectedGasPhaseNames[2] = "gas"; - expectedGasPhaseNames[3] = "Gas"; - bool found = PVTFunctionHelpers::findName( m_phaseNames, expectedGasPhaseNames, m_phaseGasIndex ); - GEOSX_ERROR_IF( !found, "Phase co2/gas is not found!" ); - - array1d< string > expectedWaterPhaseNames; - expectedWaterPhaseNames.resize( 4 ); - expectedWaterPhaseNames[0] = "Water"; - expectedWaterPhaseNames[1] = "water"; - expectedWaterPhaseNames[2] = "Liquid"; - expectedWaterPhaseNames[3] = "liquid"; - found = PVTFunctionHelpers::findName( m_phaseNames, expectedWaterPhaseNames, m_phaseLiquidIndex ); - GEOSX_ERROR_IF( !found, "Phase water/liquid is not found!" ); + std::vector< string > const expectedGasPhaseNames( { "CO2", "co2", "gas", "Gas" } ); + m_phaseGasIndex = PVTFunctionHelpers::findName( m_phaseNames, + expectedGasPhaseNames ); + GEOSX_ERROR_IF( m_phaseGasIndex < 0 || m_phaseGasIndex >= m_phaseNames.size(), + "Phase co2/gas is not found!" ); + + std::vector< string > const expectedWaterPhaseNames( { "Water", "water", "Liquid", "liquid" } ); + m_phaseLiquidIndex = PVTFunctionHelpers::findName( m_phaseNames, + expectedWaterPhaseNames ); + GEOSX_ERROR_IF( m_phaseLiquidIndex < 0 || m_phaseLiquidIndex >= m_phaseNames.size(), + "Phase water/liquid is not found!" ); createPVTModels(); } diff --git a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp index d0f228344a4..86dc36eda56 100644 --- a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp +++ b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp @@ -38,17 +38,22 @@ namespace constitutive /** * @brief Kernel wrapper class for MultiPhaseMultiComponentFluid. */ +template< typename BRINEVISCWRAPPER, + typename CO2VISCWRAPPER, + typename BRINEDENSWRAPPER, + typename CO2DENSWRAPPER, + typename FLASHWRAPPER > class MultiPhaseMultiComponentFluidUpdate final : public MultiFluidBaseUpdate { public: MultiPhaseMultiComponentFluidUpdate( localIndex const phaseGasIndex, localIndex const phaseLiquidIndex, - arrayView1d< PVTProps::BrineViscosity::KernelWrapper const > const & brineViscosityWrapper, - arrayView1d< PVTProps::FenghourCO2Viscosity::KernelWrapper const > const & co2ViscosityWrapper, - arrayView1d< PVTProps::BrineCO2Density::KernelWrapper const > const & brineDensityWrapper, - arrayView1d< PVTProps::SpanWagnerCO2Density::KernelWrapper const > const & co2DensityWrapper, - arrayView1d< PVTProps::CO2Solubility::KernelWrapper const > const & co2SolubilityWrapper, + arrayView1d< BRINEVISCWRAPPER const > const & brineViscosityWrapper, + arrayView1d< CO2VISCWRAPPER const > const & co2ViscosityWrapper, + arrayView1d< BRINEDENSWRAPPER const > const & brineDensityWrapper, + arrayView1d< CO2DENSWRAPPER const > const & co2DensityWrapper, + arrayView1d< FLASHWRAPPER const > const & co2SolubilityWrapper, arrayView1d< real64 const > const & componentMolarWeight, bool useMass, arrayView3d< real64 > const & phaseFraction, @@ -210,19 +215,19 @@ class MultiPhaseMultiComponentFluidUpdate final : public MultiFluidBaseUpdate localIndex const m_phaseLiquidIndex; /// Kernel wrapper for brine viscosity updates - arrayView1d< PVTProps::BrineViscosity::KernelWrapper const > const m_brineViscosityWrapper; + arrayView1d< BRINEVISCWRAPPER const > const m_brineViscosityWrapper; /// Kernel wrapper for CO2 viscosity updates - arrayView1d< PVTProps::FenghourCO2Viscosity::KernelWrapper const > const m_co2ViscosityWrapper; + arrayView1d< CO2VISCWRAPPER const > const m_co2ViscosityWrapper; /// Kernel wrapper for brine density updates - arrayView1d< PVTProps::BrineCO2Density::KernelWrapper const > const m_brineDensityWrapper; + arrayView1d< BRINEDENSWRAPPER const > const m_brineDensityWrapper; /// Kernel wrapper for CO2 density updates - arrayView1d< PVTProps::SpanWagnerCO2Density::KernelWrapper const > const m_co2DensityWrapper; + arrayView1d< CO2DENSWRAPPER const > const m_co2DensityWrapper; /// Kernel wrapper for phase fraction and phase component fraction updates - arrayView1d< PVTProps::CO2Solubility::KernelWrapper const > const m_co2SolubilityWrapper; + arrayView1d< FLASHWRAPPER const > const m_co2SolubilityWrapper; }; class MultiPhaseMultiComponentFluid : public MultiFluidBase @@ -245,7 +250,11 @@ class MultiPhaseMultiComponentFluid : public MultiFluidBase virtual string getCatalogName() const override { return catalogName(); } /// Type of kernel wrapper for in-kernel update - using KernelWrapper = MultiPhaseMultiComponentFluidUpdate; + using KernelWrapper = MultiPhaseMultiComponentFluidUpdate< PVTProps::BrineViscosity::KernelWrapper, + PVTProps::FenghourCO2Viscosity::KernelWrapper, + PVTProps::BrineCO2Density::KernelWrapper, + PVTProps::SpanWagnerCO2Density::KernelWrapper, + PVTProps::CO2Solubility::KernelWrapper >; /** * @brief Create an update kernel wrapper. @@ -351,17 +360,18 @@ class MultiPhaseMultiComponentFluid : public MultiFluidBase }; +template<> GEOSX_HOST_DEVICE GEOSX_FORCE_INLINE -void MultiPhaseMultiComponentFluidUpdate::compute( real64 pressure, - real64 temperature, - arraySlice1d< real64 const > const & composition, - arraySlice1d< real64 > const & phaseFraction, - arraySlice1d< real64 > const & phaseDensity, - arraySlice1d< real64 > const & phaseMassDensity, - arraySlice1d< real64 > const & phaseViscosity, - arraySlice2d< real64 > const & phaseCompFraction, - real64 & totalDensity ) const +void MultiPhaseMultiComponentFluid::KernelWrapper::compute( real64 pressure, + real64 temperature, + arraySlice1d< real64 const > const & composition, + arraySlice1d< real64 > const & phaseFraction, + arraySlice1d< real64 > const & phaseDensity, + arraySlice1d< real64 > const & phaseMassDensity, + arraySlice1d< real64 > const & phaseViscosity, + arraySlice2d< real64 > const & phaseCompFraction, + real64 & totalDensity ) const { constexpr localIndex numComps = 2; constexpr localIndex numPhases = 2; @@ -538,35 +548,36 @@ void MultiPhaseMultiComponentFluidUpdate::compute( real64 pressure, } } +template<> GEOSX_HOST_DEVICE GEOSX_FORCE_INLINE -void MultiPhaseMultiComponentFluidUpdate::compute( real64 pressure, - real64 temperature, - arraySlice1d< real64 const > const & composition, - arraySlice1d< real64 > const & phaseFraction, - arraySlice1d< real64 > const & dPhaseFraction_dPressure, - arraySlice1d< real64 > const & dPhaseFraction_dTemperature, - arraySlice2d< real64 > const & dPhaseFraction_dGlobalCompFraction, - arraySlice1d< real64 > const & phaseDensity, - arraySlice1d< real64 > const & dPhaseDensity_dPressure, - arraySlice1d< real64 > const & dPhaseDensity_dTemperature, - arraySlice2d< real64 > const & dPhaseDensity_dGlobalCompFraction, - arraySlice1d< real64 > const & phaseMassDensity, - arraySlice1d< real64 > const & dPhaseMassDensity_dPressure, - arraySlice1d< real64 > const & dPhaseMassDensity_dTemperature, - arraySlice2d< real64 > const & dPhaseMassDensity_dGlobalCompFraction, - arraySlice1d< real64 > const & phaseViscosity, - arraySlice1d< real64 > const & dPhaseViscosity_dPressure, - arraySlice1d< real64 > const & dPhaseViscosity_dTemperature, - arraySlice2d< real64 > const & dPhaseViscosity_dGlobalCompFraction, - arraySlice2d< real64 > const & phaseCompFraction, - arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, - arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, - arraySlice3d< real64 > const & dPhaseCompFraction_dGlobalCompFraction, - real64 & totalDensity, - real64 & dTotalDensity_dPressure, - real64 & dTotalDensity_dTemperature, - arraySlice1d< real64 > const & dTotalDensity_dGlobalCompFraction ) const +void MultiPhaseMultiComponentFluid::KernelWrapper::compute( real64 pressure, + real64 temperature, + arraySlice1d< real64 const > const & composition, + arraySlice1d< real64 > const & phaseFraction, + arraySlice1d< real64 > const & dPhaseFraction_dPressure, + arraySlice1d< real64 > const & dPhaseFraction_dTemperature, + arraySlice2d< real64 > const & dPhaseFraction_dGlobalCompFraction, + arraySlice1d< real64 > const & phaseDensity, + arraySlice1d< real64 > const & dPhaseDensity_dPressure, + arraySlice1d< real64 > const & dPhaseDensity_dTemperature, + arraySlice2d< real64 > const & dPhaseDensity_dGlobalCompFraction, + arraySlice1d< real64 > const & phaseMassDensity, + arraySlice1d< real64 > const & dPhaseMassDensity_dPressure, + arraySlice1d< real64 > const & dPhaseMassDensity_dTemperature, + arraySlice2d< real64 > const & dPhaseMassDensity_dGlobalCompFraction, + arraySlice1d< real64 > const & phaseViscosity, + arraySlice1d< real64 > const & dPhaseViscosity_dPressure, + arraySlice1d< real64 > const & dPhaseViscosity_dTemperature, + arraySlice2d< real64 > const & dPhaseViscosity_dGlobalCompFraction, + arraySlice2d< real64 > const & phaseCompFraction, + arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, + arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, + arraySlice3d< real64 > const & dPhaseCompFraction_dGlobalCompFraction, + real64 & totalDensity, + real64 & dTotalDensity_dPressure, + real64 & dTotalDensity_dTemperature, + arraySlice1d< real64 > const & dTotalDensity_dGlobalCompFraction ) const { // 0. make shortcut structs to avoid long names (TODO maybe remove) CompositionalVarContainer< 1 > phaseFrac { diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp index a2bc7c50abc..fe10856da42 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp @@ -40,28 +40,19 @@ BrineCO2Density::BrineCO2Density( array1d< string > const & inputPara, componentNames, componentMolarWeight ) { - array1d< string > expectedCO2ComponentNames; - expectedCO2ComponentNames.resize( 2 ); - expectedCO2ComponentNames[0] = "CO2"; - expectedCO2ComponentNames[1] = "co2"; - bool found = PVTFunctionHelpers::findName( componentNames, expectedCO2ComponentNames, m_CO2Index ); - GEOSX_ERROR_IF( !found, "Component CO2 is not found!" ); - - array1d< string > expectedWaterComponentNames; - expectedWaterComponentNames.resize( 2 ); - expectedWaterComponentNames[0] = "Water"; - expectedWaterComponentNames[1] = "water"; - found = PVTFunctionHelpers::findName( componentNames, expectedWaterComponentNames, m_waterIndex ); - GEOSX_ERROR_IF( !found, "Component Water/Brine is not found!" ); + std::vector< string > const expectedCO2ComponentNames( { "CO2", "co2" } ); + m_CO2Index = PVTFunctionHelpers::findName( componentNames, expectedCO2ComponentNames ); + GEOSX_ERROR_IF( m_CO2Index < 0 || m_CO2Index >= componentNames.size(), "Component CO2 is not found!" ); + + std::vector< string > const expectedWaterComponentNames( { "Water", "water" } ); + m_waterIndex = PVTFunctionHelpers::findName( componentNames, expectedWaterComponentNames ); + GEOSX_ERROR_IF( m_waterIndex < 0 || m_waterIndex >= componentNames.size(), "Component Water/Brine is not found!" ); makeTable( inputPara ); } void BrineCO2Density::makeTable( array1d< string > const & inputPara ) { - array1d< array1d< real64 > > coordinates; - coordinates.resize( 2 ); - real64 TStart = -1.0; real64 TEnd = -1.0; real64 dT = -1.0; @@ -89,24 +80,22 @@ void BrineCO2Density::makeTable( array1d< string > const & inputPara ) GEOSX_ERROR( "Invalid BrineCO2Density argument:" + string( e.what()) ); } + PTTableCoordinates tableCoords; for( real64 P = PStart; P <= PEnd; P += dP ) { - coordinates[0].emplace_back( P ); + tableCoords.appendPressure( P ); } for( real64 T = TStart; T <= TEnd; T += dT ) { - coordinates[1].emplace_back( T ); + tableCoords.appendTemperature( T ); } - localIndex const nP = coordinates[0].size(); - localIndex const nT = coordinates[1].size(); - - array1d< real64 > values( nP * nT ); - calculateBrineDensity( coordinates, salinity, values ); + array1d< real64 > values( tableCoords.nPressures() * tableCoords.nTemperatures() ); + calculateBrineDensity( tableCoords.get(), salinity, values ); FunctionManager & functionManager = getGlobalState().getFunctionManager(); m_brineDensityTable = dynamicCast< TableFunction * >( functionManager.createChild( "TableFunction", "brineDensityTable" ) ); - m_brineDensityTable->setTableCoordinates( coordinates ); + m_brineDensityTable->setTableCoordinates( tableCoords.get() ); m_brineDensityTable->setTableValues( values ); m_brineDensityTable->reInitializeFunction(); m_brineDensityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp index 028e1ab26e2..55fb3e53aa6 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp @@ -139,46 +139,31 @@ CO2Solubility::CO2Solubility( array1d< string > const & inputPara, GEOSX_ERROR_IF( phaseNames.size() != 2, "The CO2Solubility model is a two-phase model" ); GEOSX_ERROR_IF( componentNames.size() != 2, "The CO2Solubility model is a two-component model" ); - array1d< string > expectedCO2ComponentNames; - expectedCO2ComponentNames.resize( 2 ); - expectedCO2ComponentNames[0] = "CO2"; - expectedCO2ComponentNames[1] = "co2"; - bool found = PVTFunctionHelpers::findName( componentNames, expectedCO2ComponentNames, m_CO2Index ); - GEOSX_ERROR_IF( !found, "Component CO2 is not found!" ); - - array1d< string > expectedWaterComponentNames; - expectedWaterComponentNames.resize( 2 ); - expectedWaterComponentNames[0] = "Water"; - expectedWaterComponentNames[1] = "water"; - found = PVTFunctionHelpers::findName( componentNames, expectedWaterComponentNames, m_waterIndex ); - GEOSX_ERROR_IF( !found, "Component Water/Brine is not found!" ); - - array1d< string > expectedGasPhaseNames; - expectedGasPhaseNames.resize( 4 ); - expectedGasPhaseNames[0] = "CO2"; - expectedGasPhaseNames[1] = "co2"; - expectedGasPhaseNames[2] = "gas"; - expectedGasPhaseNames[3] = "Gas"; - found = PVTFunctionHelpers::findName( phaseNames, expectedGasPhaseNames, m_phaseGasIndex ); - GEOSX_ERROR_IF( !found, "Phase co2/gas is not found!" ); - - array1d< string > expectedWaterPhaseNames; - expectedWaterPhaseNames.resize( 4 ); - expectedWaterPhaseNames[0] = "Water"; - expectedWaterPhaseNames[1] = "water"; - expectedWaterPhaseNames[2] = "Liquid"; - expectedWaterPhaseNames[3] = "liquid"; - found = PVTFunctionHelpers::findName( phaseNames, expectedWaterPhaseNames, m_phaseLiquidIndex ); - GEOSX_ERROR_IF( !found, "Phase water/liquid is not found!" ); + std::vector< string > const expectedCO2ComponentNames( { "CO2", "co2" } ); + m_CO2Index = PVTFunctionHelpers::findName( componentNames, expectedCO2ComponentNames ); + GEOSX_ERROR_IF( m_CO2Index < 0 || m_CO2Index >= componentNames.size(), "Component CO2 is not found!" ); + + std::vector< string > const expectedWaterComponentNames( { "Water", "water" } ); + m_waterIndex = PVTFunctionHelpers::findName( componentNames, expectedWaterComponentNames ); + GEOSX_ERROR_IF( m_waterIndex < 0 || m_waterIndex >= componentNames.size(), "Component Water/Brine is not found!" ); + + std::vector< string > const expectedGasPhaseNames( { "CO2", "co2", "gas", "Gas" } ); + m_phaseGasIndex = PVTFunctionHelpers::findName( phaseNames, + expectedGasPhaseNames ); + GEOSX_ERROR_IF( m_phaseGasIndex < 0 || m_phaseGasIndex >= phaseNames.size(), + "Phase co2/gas is not found!" ); + + std::vector< string > const expectedWaterPhaseNames( { "Water", "water", "Liquid", "liquid" } ); + m_phaseLiquidIndex = PVTFunctionHelpers::findName( phaseNames, + expectedWaterPhaseNames ); + GEOSX_ERROR_IF( m_phaseLiquidIndex < 0 || m_phaseLiquidIndex >= phaseNames.size(), + "Phase water/liquid is not found!" ); makeTable( inputPara ); } void CO2Solubility::makeTable( array1d< string > const & inputPara ) { - array1d< array1d< real64 > > coordinates; - coordinates.resize( 2 ); - real64 TStart = -1.0; real64 TEnd = -1.0; real64 dT = -1.0; @@ -206,23 +191,22 @@ void CO2Solubility::makeTable( array1d< string > const & inputPara ) GEOSX_ERROR( "Invalid CO2Solubility argument:" + string( e.what()) ); } + PTTableCoordinates tableCoords; for( real64 P = PStart; P <= PEnd; P += dP ) { - coordinates[0].emplace_back( P ); + tableCoords.appendPressure( P ); } for( real64 T = TStart; T <= TEnd; T += dT ) { - coordinates[1].emplace_back( T ); + tableCoords.appendTemperature( T ); } - localIndex const nP = coordinates[0].size(); - localIndex const nT = coordinates[1].size(); - array1d< real64 > values( nP * nT ); - calculateCO2Solubility( coordinates, salinity, values ); + array1d< real64 > values( tableCoords.nPressures() * tableCoords.nTemperatures() ); + calculateCO2Solubility( tableCoords.get(), salinity, values ); FunctionManager & functionManager = getGlobalState().getFunctionManager(); m_CO2SolubilityTable = dynamicCast< TableFunction * >( functionManager.createChild( "TableFunction", "CO2SolubilityTable" ) ); - m_CO2SolubilityTable->setTableCoordinates( coordinates ); + m_CO2SolubilityTable->setTableCoordinates( tableCoords.get() ); m_CO2SolubilityTable->setTableValues( values ); m_CO2SolubilityTable->reInitializeFunction(); m_CO2SolubilityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp index 2f3f27cd8bc..90d643aafaf 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp @@ -18,6 +18,7 @@ #include "constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp" #include "constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp" #include "managers/Functions/FunctionManager.hpp" #include "managers/GeosxState.hpp" @@ -43,9 +44,6 @@ FenghourCO2Viscosity::FenghourCO2Viscosity( array1d< string > const & inputPara, void FenghourCO2Viscosity::makeTable( array1d< string > const & inputPara ) { - array1d< array1d< real64 > > coordinates; - coordinates.resize( 2 ); - real64 TStart = -1.0; real64 TEnd = -1.0; real64 dT = -1.0; @@ -70,25 +68,26 @@ void FenghourCO2Viscosity::makeTable( array1d< string > const & inputPara ) GEOSX_ERROR( "Invalid FenghourCO2Viscosity argument:" + string( e.what()) ); } + PTTableCoordinates tableCoords; for( real64 P = PStart; P <= PEnd; P += dP ) { - coordinates[0].emplace_back( P ); + tableCoords.appendPressure( P ); } for( real64 T = TStart; T <= TEnd; T += dT ) { - coordinates[1].emplace_back( T ); + tableCoords.appendTemperature( T ); } - localIndex nP = coordinates[0].size(); - localIndex nT = coordinates[1].size(); + localIndex const nP = tableCoords.nPressures(); + localIndex const nT = tableCoords.nTemperatures(); array1d< real64 > density( nP * nT ); array1d< real64 > viscosity( nP * nT ); - SpanWagnerCO2Density::calculateCO2Density( coordinates, density ); - calculateCO2Viscosity( coordinates, density, viscosity ); + SpanWagnerCO2Density::calculateCO2Density( tableCoords.get(), density ); + calculateCO2Viscosity( tableCoords.get(), density, viscosity ); FunctionManager & functionManager = getGlobalState().getFunctionManager(); m_CO2ViscosityTable = dynamicCast< TableFunction * >( functionManager.createChild( "TableFunction", "CO2ViscosityTable" ) ); - m_CO2ViscosityTable->setTableCoordinates( coordinates ); + m_CO2ViscosityTable->setTableCoordinates( tableCoords.get() ); m_CO2ViscosityTable->setTableValues( viscosity ); m_CO2ViscosityTable->reInitializeFunction(); m_CO2ViscosityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp index e28a1ac7d25..bea2944b70f 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp @@ -35,32 +35,40 @@ struct PVTFunctionHelpers * @brief Look for the expectedNames in the names provided by the user * @param[in] inputNames phase or component names provided by the user * @param[in] expectedNames expected names that can be accepted by GEOSX - * @param[inout] id the index of the phase or component that was found - * @return true is an expectedName was found in the inputNames, false otherwise + * @return the index of the phase or component that was found */ - static bool - findName( array1d< string > const & inputNames, - array1d< string > const & expectedNames, - localIndex & id ) + template< typename InputRange, typename ExpectedRange > + static localIndex + findName( InputRange const & inputNames, + ExpectedRange const & expectedNames ) { - id = -1; - for( localIndex i = 0; i < inputNames.size(); ++i ) - { - string const input = inputNames[i]; - for( localIndex j = 0; j < expectedNames.size(); ++j ) - { - if( input == expectedNames[j] ) - { - id = i; - return true; - } - } - } - return false; + using std::begin; + using std::end; + auto it = std::find_first_of( begin( inputNames ), end( inputNames ), begin( expectedNames ), end( expectedNames ) ); + localIndex const id = std::distance( begin( inputNames ), it ); + return id; } }; +class PTTableCoordinates +{ +public: + PTTableCoordinates() + { coords.resize( 2 ); } + + localIndex nPressures() const { return coords[0].size(); } + localIndex nTemperatures() const { return coords[1].size(); } + + void appendPressure( const real64 & pres ) { coords[0].emplace_back( pres ); } + void appendTemperature( const real64 & temp ) { coords[1].emplace_back( temp ); } + + array1d< array1d< real64 > > const & get() const { return coords; } + +private: + array1d< array1d< real64 > > coords; +}; + } // namespace PVTProps } // namespace constitutive diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp index 8d0881ed1cc..3fff987d77d 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp @@ -147,21 +147,15 @@ SpanWagnerCO2Density::SpanWagnerCO2Density( array1d< string > const & inputPara, componentNames, componentMolarWeight ) { - array1d< string > expectedCO2ComponentNames; - expectedCO2ComponentNames.resize( 2 ); - expectedCO2ComponentNames[0] = "CO2"; - expectedCO2ComponentNames[1] = "co2"; - bool found = PVTFunctionHelpers::findName( componentNames, expectedCO2ComponentNames, m_CO2Index ); - GEOSX_ERROR_IF( !found, "Component CO2 is not found!" ); + std::vector< string > const expectedCO2ComponentNames( { "CO2", "co2" } ); + m_CO2Index = PVTFunctionHelpers::findName( componentNames, expectedCO2ComponentNames ); + GEOSX_ERROR_IF( m_CO2Index < 0 || m_CO2Index >= componentNames.size(), "Component CO2 is not found!" ); makeTable( inputPara ); } void SpanWagnerCO2Density::makeTable( array1d< string > const & inputPara ) { - array1d< array1d< real64 > > coordinates; - coordinates.resize( 2 ); - real64 TStart = -1.0; real64 TEnd = -1.0; real64 dT = -1.0; @@ -186,23 +180,24 @@ void SpanWagnerCO2Density::makeTable( array1d< string > const & inputPara ) GEOSX_ERROR( "Invalid SpanWagnerCO2Density argument:" + string( e.what()) ); } + PTTableCoordinates tableCoords; for( real64 P = PStart; P <= PEnd; P += dP ) { - coordinates[0].emplace_back( P ); + tableCoords.appendPressure( P ); } for( real64 T = TStart; T <= TEnd; T += dT ) { - coordinates[1].emplace_back( T ); + tableCoords.appendTemperature( T ); } - localIndex const nP = coordinates[0].size(); - localIndex const nT = coordinates[1].size(); + localIndex const nP = tableCoords.nPressures(); + localIndex const nT = tableCoords.nTemperatures(); array1d< real64 > values( nP * nT ); - calculateCO2Density( coordinates, values ); + calculateCO2Density( tableCoords.get(), values ); FunctionManager & functionManager = getGlobalState().getFunctionManager(); m_CO2DensityTable = dynamicCast< TableFunction * >( functionManager.createChild( "TableFunction", "CO2DensityTable" ) ); - m_CO2DensityTable->setTableCoordinates( coordinates ); + m_CO2DensityTable->setTableCoordinates( tableCoords.get() ); m_CO2DensityTable->setTableValues( values ); m_CO2DensityTable->reInitializeFunction(); m_CO2DensityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); From dd748f521d9a8e66c2745c9b58127697178e11eb Mon Sep 17 00:00:00 2001 From: Francois Hamon Date: Wed, 10 Mar 2021 20:01:21 -0800 Subject: [PATCH 06/10] addressed Thomas' comments --- .../fluid/MultiPhaseMultiComponentFluid.cpp | 4 +- .../PVTFunctions/BrineCO2DensityFunction.cpp | 74 ++------ .../PVTFunctions/BrineCO2DensityFunction.hpp | 11 +- .../PVTFunctions/BrineViscosityFunction.cpp | 8 +- .../PVTFunctions/BrineViscosityFunction.hpp | 6 +- .../PVTFunctions/CO2SolubilityFunction.cpp | 73 ++------ .../PVTFunctions/CO2SolubilityFunction.hpp | 11 +- .../FenghourCO2ViscosityFunction.cpp | 67 ++----- .../FenghourCO2ViscosityFunction.hpp | 13 +- .../fluid/PVTFunctions/PVTFunctionHelpers.hpp | 115 ++++++++++-- .../SpanWagnerCO2DensityFunction.cpp | 71 ++------ .../SpanWagnerCO2DensityFunction.hpp | 11 +- .../unitTests/testCO2BrinePVTModels.cpp | 26 +-- .../constitutive/unitTests/testMultiFluid.cpp | 172 +++++++++--------- 14 files changed, 301 insertions(+), 361 deletions(-) diff --git a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp index 34b2188d9a6..52ebcba7f64 100644 --- a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp +++ b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp @@ -76,13 +76,13 @@ void MultiPhaseMultiComponentFluid::postProcessInput() GEOSX_ERROR_IF( numComps != 2, "The number of components in this model should be equal to 2" ); GEOSX_ERROR_IF( m_phasePVTParaFiles.size() != 2, "The number of phasePVTParaFiles is not the same as the number of phases!" ); - std::vector< string > const expectedGasPhaseNames( { "CO2", "co2", "gas", "Gas" } ); + char const * expectedGasPhaseNames[] = { "CO2", "co2", "gas", "Gas" }; m_phaseGasIndex = PVTFunctionHelpers::findName( m_phaseNames, expectedGasPhaseNames ); GEOSX_ERROR_IF( m_phaseGasIndex < 0 || m_phaseGasIndex >= m_phaseNames.size(), "Phase co2/gas is not found!" ); - std::vector< string > const expectedWaterPhaseNames( { "Water", "water", "Liquid", "liquid" } ); + char const * expectedWaterPhaseNames[] = { "Water", "water", "Liquid", "liquid" }; m_phaseLiquidIndex = PVTFunctionHelpers::findName( m_phaseNames, expectedWaterPhaseNames ); GEOSX_ERROR_IF( m_phaseLiquidIndex < 0 || m_phaseLiquidIndex >= m_phaseNames.size(), diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp index fe10856da42..4d4dcac0317 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp @@ -18,7 +18,6 @@ #include "constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp" -#include "constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp" #include "managers/Functions/FunctionManager.hpp" #include "managers/GeosxState.hpp" @@ -33,77 +32,43 @@ namespace constitutive namespace PVTProps { -BrineCO2Density::BrineCO2Density( array1d< string > const & inputPara, - array1d< string > const & componentNames, +BrineCO2Density::BrineCO2Density( string_array const & inputPara, + string_array const & componentNames, array1d< real64 > const & componentMolarWeight ): PVTFunctionBase( inputPara[1], componentNames, componentMolarWeight ) { - std::vector< string > const expectedCO2ComponentNames( { "CO2", "co2" } ); + char const * expectedCO2ComponentNames[] = { "CO2", "co2" }; m_CO2Index = PVTFunctionHelpers::findName( componentNames, expectedCO2ComponentNames ); GEOSX_ERROR_IF( m_CO2Index < 0 || m_CO2Index >= componentNames.size(), "Component CO2 is not found!" ); - std::vector< string > const expectedWaterComponentNames( { "Water", "water" } ); + char const * expectedWaterComponentNames[] = { "Water", "water" }; m_waterIndex = PVTFunctionHelpers::findName( componentNames, expectedWaterComponentNames ); GEOSX_ERROR_IF( m_waterIndex < 0 || m_waterIndex >= componentNames.size(), "Component Water/Brine is not found!" ); makeTable( inputPara ); } -void BrineCO2Density::makeTable( array1d< string > const & inputPara ) +void BrineCO2Density::makeTable( string_array const & inputPara ) { - real64 TStart = -1.0; - real64 TEnd = -1.0; - real64 dT = -1.0; - real64 PStart = -1.0; - real64 PEnd = -1.0; - real64 dP = -1.0; - real64 salinity = 0.0; - - GEOSX_ERROR_IF( inputPara.size() < 9, "Invalid BrineCO2Density input!" ); - - try - { - PStart = stod( inputPara[2] ); - PEnd = stod( inputPara[3] ); - dP = stod( inputPara[4] ); - - TStart = stod( inputPara[5] ); - TEnd = stod( inputPara[6] ); - dT = stod( inputPara[7] ); - - salinity = stod( inputPara[8] ); - } - catch( const std::invalid_argument & e ) - { - GEOSX_ERROR( "Invalid BrineCO2Density argument:" + string( e.what()) ); - } - PTTableCoordinates tableCoords; - for( real64 P = PStart; P <= PEnd; P += dP ) - { - tableCoords.appendPressure( P ); - } - for( real64 T = TStart; T <= TEnd; T += dT ) - { - tableCoords.appendTemperature( T ); - } + real64 const salinity = PVTFunctionHelpers::initializePropertyTableWithSalinity( inputPara, tableCoords ); - array1d< real64 > values( tableCoords.nPressures() * tableCoords.nTemperatures() ); - calculateBrineDensity( tableCoords.get(), salinity, values ); + array1d< real64 > densities( tableCoords.nPressures() * tableCoords.nTemperatures() ); + calculateBrineDensity( tableCoords, salinity, densities ); FunctionManager & functionManager = getGlobalState().getFunctionManager(); m_brineDensityTable = dynamicCast< TableFunction * >( functionManager.createChild( "TableFunction", "brineDensityTable" ) ); - m_brineDensityTable->setTableCoordinates( tableCoords.get() ); - m_brineDensityTable->setTableValues( values ); + m_brineDensityTable->setTableCoordinates( tableCoords.getCoords() ); + m_brineDensityTable->setTableValues( densities ); m_brineDensityTable->reInitializeFunction(); m_brineDensityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); } -void BrineCO2Density::calculateBrineDensity( array1d< array1d< real64 > > const & coordinates, +void BrineCO2Density::calculateBrineDensity( PTTableCoordinates const & tableCoords, real64 const & salinity, - array1d< real64 > const & values ) + array1d< real64 > const & densities ) { // these coefficients come from Phillips et al. (1981), equations (4) and (5), pages 14 and 15 constexpr real64 c1 = -9.9595; @@ -119,20 +84,17 @@ void BrineCO2Density::calculateBrineDensity( array1d< array1d< real64 > > const constexpr real64 CC = -8.750567; constexpr real64 DD = 2.663107; - localIndex const numPressures = coordinates[0].size(); - localIndex const numTemperatures = coordinates[1].size(); - - for( localIndex i = 0; i < numPressures; ++i ) + for( localIndex i = 0; i < tableCoords.nPressures(); ++i ) { - real64 const P = coordinates[0][i] / 1e5; + real64 const P = tableCoords.getPressure( i ) / 1e5; - for( localIndex j = 0; j < numTemperatures; ++j ) + for( localIndex j = 0; j < tableCoords.nTemperatures(); ++j ) { // see Phillips et al. (1981), equations (4) and (5), pages 14 and 15 real64 const x = c1 * exp( a1 * salinity ) - + c2 * exp( a2 * coordinates[1][j] ) + + c2 * exp( a2 * tableCoords.getTemperature( j ) ) + c3 * exp( a3 * P ); - values[j*numPressures+i] = (AA + BB * x + CC * x * x + DD * x * x * x) * 1000.0; + densities[j*tableCoords.nPressures()+i] = (AA + BB * x + CC * x * x + DD * x * x * x) * 1000.0; } } } @@ -146,7 +108,7 @@ BrineCO2Density::KernelWrapper BrineCO2Density::createKernelWrapper() m_waterIndex ); } -REGISTER_CATALOG_ENTRY( PVTFunctionBase, BrineCO2Density, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) +REGISTER_CATALOG_ENTRY( PVTFunctionBase, BrineCO2Density, string_array const &, string_array const &, array1d< real64 > const & ) } // namespace PVTProps diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp index 591c357149b..d95ffcfe6cd 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp @@ -21,6 +21,7 @@ #include "PVTFunctionBase.hpp" +#include "constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp" #include "managers/Functions/TableFunction.hpp" namespace geosx @@ -88,8 +89,8 @@ class BrineCO2Density : public PVTFunctionBase { public: - BrineCO2Density( array1d< string > const & inputPara, - array1d< string > const & componentNames, + BrineCO2Density( string_array const & inputPara, + string_array const & componentNames, array1d< real64 > const & componentMolarWeight ); ~BrineCO2Density() override {} @@ -115,11 +116,11 @@ class BrineCO2Density : public PVTFunctionBase private: - void makeTable( array1d< string > const & inputPara ); + void makeTable( string_array const & inputPara ); - void calculateBrineDensity( array1d< array1d< real64 > > const & coordinates, + void calculateBrineDensity( PVTProps::PTTableCoordinates const & tableCoords, real64 const & salinity, - array1d< real64 > const & values ); + array1d< real64 > const & densities ); /// Table with brine density tabulated as a function of (P,T,sal) TableFunction * m_brineDensityTable; diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.cpp index 92fdbc551dc..579179dfb1d 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.cpp @@ -29,8 +29,8 @@ namespace constitutive namespace PVTProps { -BrineViscosity::BrineViscosity( array1d< string > const & inputPara, - array1d< string > const & componentNames, +BrineViscosity::BrineViscosity( string_array const & inputPara, + string_array const & componentNames, array1d< real64 > const & componentMolarWeight ): PVTFunctionBase( inputPara[1], componentNames, @@ -39,7 +39,7 @@ BrineViscosity::BrineViscosity( array1d< string > const & inputPara, makeCoefficients( inputPara ); } -void BrineViscosity::makeCoefficients( array1d< string > const & inputPara ) +void BrineViscosity::makeCoefficients( string_array const & inputPara ) { // these coefficients come from Phillips et al. (1981), equation (1), pages 5-6 constexpr real64 a = 0.0816; @@ -74,7 +74,7 @@ BrineViscosity::KernelWrapper BrineViscosity::createKernelWrapper() m_coef1 ); } -REGISTER_CATALOG_ENTRY( PVTFunctionBase, BrineViscosity, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) +REGISTER_CATALOG_ENTRY( PVTFunctionBase, BrineViscosity, string_array const &, string_array const &, array1d< real64 > const & ) } // end namespace PVTProps diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp index e7d3ba63933..8a886184f96 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp @@ -80,8 +80,8 @@ class BrineViscosity : public PVTFunctionBase { public: - BrineViscosity( array1d< string > const & inputPara, - array1d< string > const & componentNames, + BrineViscosity( string_array const & inputPara, + string_array const & componentNames, array1d< real64 > const & componentMolarWeight ); ~BrineViscosity() override {} @@ -106,7 +106,7 @@ class BrineViscosity : public PVTFunctionBase private: - void makeCoefficients( array1d< string > const & inputPara ); + void makeCoefficients( string_array const & inputPara ); real64 m_coef0; diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp index 55fb3e53aa6..5667cea57e2 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp @@ -128,9 +128,9 @@ real64 Par( real64 const & T, real64 const & P, real64 const * cc ) } -CO2Solubility::CO2Solubility( array1d< string > const & inputPara, - array1d< string > const & phaseNames, - array1d< string > const & componentNames, +CO2Solubility::CO2Solubility( string_array const & inputPara, + string_array const & phaseNames, + string_array const & componentNames, array1d< real64 > const & componentMolarWeight ): FlashModelBase( inputPara[1], componentNames, @@ -139,21 +139,21 @@ CO2Solubility::CO2Solubility( array1d< string > const & inputPara, GEOSX_ERROR_IF( phaseNames.size() != 2, "The CO2Solubility model is a two-phase model" ); GEOSX_ERROR_IF( componentNames.size() != 2, "The CO2Solubility model is a two-component model" ); - std::vector< string > const expectedCO2ComponentNames( { "CO2", "co2" } ); + char const * expectedCO2ComponentNames[] = { "CO2", "co2" }; m_CO2Index = PVTFunctionHelpers::findName( componentNames, expectedCO2ComponentNames ); GEOSX_ERROR_IF( m_CO2Index < 0 || m_CO2Index >= componentNames.size(), "Component CO2 is not found!" ); - std::vector< string > const expectedWaterComponentNames( { "Water", "water" } ); + char const * expectedWaterComponentNames[] = { "Water", "water" }; m_waterIndex = PVTFunctionHelpers::findName( componentNames, expectedWaterComponentNames ); GEOSX_ERROR_IF( m_waterIndex < 0 || m_waterIndex >= componentNames.size(), "Component Water/Brine is not found!" ); - std::vector< string > const expectedGasPhaseNames( { "CO2", "co2", "gas", "Gas" } ); + char const * expectedGasPhaseNames[] = { "CO2", "co2", "gas", "Gas" }; m_phaseGasIndex = PVTFunctionHelpers::findName( phaseNames, expectedGasPhaseNames ); GEOSX_ERROR_IF( m_phaseGasIndex < 0 || m_phaseGasIndex >= phaseNames.size(), "Phase co2/gas is not found!" ); - std::vector< string > const expectedWaterPhaseNames( { "Water", "water", "Liquid", "liquid" } ); + char const * expectedWaterPhaseNames[] = { "Water", "water", "Liquid", "liquid" }; m_phaseLiquidIndex = PVTFunctionHelpers::findName( phaseNames, expectedWaterPhaseNames ); GEOSX_ERROR_IF( m_phaseLiquidIndex < 0 || m_phaseLiquidIndex >= phaseNames.size(), @@ -162,57 +162,23 @@ CO2Solubility::CO2Solubility( array1d< string > const & inputPara, makeTable( inputPara ); } -void CO2Solubility::makeTable( array1d< string > const & inputPara ) +void CO2Solubility::makeTable( string_array const & inputPara ) { - real64 TStart = -1.0; - real64 TEnd = -1.0; - real64 dT = -1.0; - real64 PStart = -1.0; - real64 PEnd = -1.0; - real64 dP = -1.0; - real64 salinity = 0; - - GEOSX_ERROR_IF( inputPara.size() < 9, "Invalid CO2Solubility input!" ); - - try - { - PStart = stod( inputPara[2] ); - PEnd = stod( inputPara[3] ); - dP = stod( inputPara[4] ); - - TStart = stod( inputPara[5] ); - TEnd = stod( inputPara[6] ); - dT = stod( inputPara[7] ); - - salinity = stod( inputPara[8] ); - } - catch( const std::invalid_argument & e ) - { - GEOSX_ERROR( "Invalid CO2Solubility argument:" + string( e.what()) ); - } - PTTableCoordinates tableCoords; - for( real64 P = PStart; P <= PEnd; P += dP ) - { - tableCoords.appendPressure( P ); - } - for( real64 T = TStart; T <= TEnd; T += dT ) - { - tableCoords.appendTemperature( T ); - } + real64 const salinity = PVTFunctionHelpers::initializePropertyTableWithSalinity( inputPara, tableCoords ); array1d< real64 > values( tableCoords.nPressures() * tableCoords.nTemperatures() ); - calculateCO2Solubility( tableCoords.get(), salinity, values ); + calculateCO2Solubility( tableCoords, salinity, values ); FunctionManager & functionManager = getGlobalState().getFunctionManager(); m_CO2SolubilityTable = dynamicCast< TableFunction * >( functionManager.createChild( "TableFunction", "CO2SolubilityTable" ) ); - m_CO2SolubilityTable->setTableCoordinates( tableCoords.get() ); + m_CO2SolubilityTable->setTableCoordinates( tableCoords.getCoords() ); m_CO2SolubilityTable->setTableValues( values ); m_CO2SolubilityTable->reInitializeFunction(); m_CO2SolubilityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); } -void CO2Solubility::calculateCO2Solubility( array1d< array1d< real64 > > const & coordinates, +void CO2Solubility::calculateCO2Solubility( PTTableCoordinates const & tableCoords, real64 const & salinity, array1d< real64 > const & values ) { @@ -223,16 +189,13 @@ void CO2Solubility::calculateCO2Solubility( array1d< array1d< real64 > > const & constexpr real64 lambda[] = { -0.411370585, 6.07632013e-4, 97.5347708, 0, 0, 0, 0, -0.0237622469, 0.0170656236, 0, 1.41335834e-5 }; constexpr real64 zeta[] = { 3.36389723e-4, -1.98298980e-5, 0, 0, 0, 0, 0, 2.12220830e-3, -5.24873303e-3, 0, 0 }; - localIndex const numPressures = coordinates[0].size(); - localIndex const numTemperatures = coordinates[1].size(); - - for( localIndex i = 0; i < numPressures; ++i ) + for( localIndex i = 0; i < tableCoords.nPressures(); ++i ) { - real64 const P = coordinates[0][i] / P_Pa_f; + real64 const P = tableCoords.getPressure( i ) / P_Pa_f; - for( localIndex j = 0; j < numTemperatures; ++j ) + for( localIndex j = 0; j < tableCoords.nTemperatures(); ++j ) { - real64 const T = coordinates[1][j]; + real64 const T = tableCoords.getTemperature( j ); // compute reduced volume by solving the CO2 equation of state real64 V_r = 0.0; @@ -246,7 +209,7 @@ void CO2Solubility::calculateCO2Solubility( array1d< array1d< real64 > > const & // mole fraction of CO2 in vapor phase, equation (4) of Duan and Sun (2003) real64 const y_CO2 = (P - detail::PWater( T ))/P; - values[j*numPressures+i] = y_CO2 * P / exp( logK ); + values[j*tableCoords.nPressures()+i] = y_CO2 * P / exp( logK ); } } } @@ -301,7 +264,7 @@ CO2Solubility::KernelWrapper CO2Solubility::createKernelWrapper() m_phaseLiquidIndex ); } -REGISTER_CATALOG_ENTRY( FlashModelBase, CO2Solubility, array1d< string > const &, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) +REGISTER_CATALOG_ENTRY( FlashModelBase, CO2Solubility, string_array const &, string_array const &, string_array const &, array1d< real64 > const & ) } // end namespace PVTProps diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp index bf05146f60b..1d75b488603 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp @@ -21,6 +21,7 @@ #include "FlashModelBase.hpp" +#include "constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp" #include "managers/Functions/TableFunction.hpp" namespace geosx @@ -103,9 +104,9 @@ class CO2Solubility : public FlashModelBase { public: - CO2Solubility( array1d< string > const & inputPara, - array1d< string > const & phaseNames, - array1d< string > const & componentNames, + CO2Solubility( string_array const & inputPara, + string_array const & phaseNames, + string_array const & componentNames, array1d< real64 > const & componentMolarWeight ); ~CO2Solubility() override {} @@ -125,9 +126,9 @@ class CO2Solubility : public FlashModelBase private: - void makeTable( array1d< string > const & inputPara ); + void makeTable( string_array const & inputPara ); - void calculateCO2Solubility( array1d< array1d< real64 > > const & coordinates, + void calculateCO2Solubility( PVTProps::PTTableCoordinates const & tableCoords, real64 const & salinity, array1d< real64 > const & values ); diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp index 90d643aafaf..4119c335f47 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp @@ -18,7 +18,6 @@ #include "constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp" -#include "constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp" #include "constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp" #include "managers/Functions/FunctionManager.hpp" #include "managers/GeosxState.hpp" @@ -32,8 +31,8 @@ namespace constitutive namespace PVTProps { -FenghourCO2Viscosity::FenghourCO2Viscosity( array1d< string > const & inputPara, - array1d< string > const & componentNames, +FenghourCO2Viscosity::FenghourCO2Viscosity( string_array const & inputPara, + string_array const & componentNames, array1d< real64 > const & componentMolarWeight ): PVTFunctionBase( inputPara[1], componentNames, @@ -42,52 +41,21 @@ FenghourCO2Viscosity::FenghourCO2Viscosity( array1d< string > const & inputPara, makeTable( inputPara ); } -void FenghourCO2Viscosity::makeTable( array1d< string > const & inputPara ) +void FenghourCO2Viscosity::makeTable( string_array const & inputPara ) { - real64 TStart = -1.0; - real64 TEnd = -1.0; - real64 dT = -1.0; - real64 PStart = -1.0; - real64 PEnd = -1.0; - real64 dP = -1.0; - - GEOSX_ERROR_IF( inputPara.size() < 8, "Invalid FenghourCO2Viscosity input!" ); - - try - { - PStart = stod( inputPara[2] ); - PEnd = stod( inputPara[3] ); - dP = stod( inputPara[4] ); - - TStart = stod( inputPara[5] ); - TEnd = stod( inputPara[6] ); - dT = stod( inputPara[7] ); - } - catch( const std::invalid_argument & e ) - { - GEOSX_ERROR( "Invalid FenghourCO2Viscosity argument:" + string( e.what()) ); - } - PTTableCoordinates tableCoords; - for( real64 P = PStart; P <= PEnd; P += dP ) - { - tableCoords.appendPressure( P ); - } - for( real64 T = TStart; T <= TEnd; T += dT ) - { - tableCoords.appendTemperature( T ); - } + PVTFunctionHelpers::initializePropertyTable( inputPara, tableCoords ); localIndex const nP = tableCoords.nPressures(); localIndex const nT = tableCoords.nTemperatures(); array1d< real64 > density( nP * nT ); array1d< real64 > viscosity( nP * nT ); - SpanWagnerCO2Density::calculateCO2Density( tableCoords.get(), density ); - calculateCO2Viscosity( tableCoords.get(), density, viscosity ); + SpanWagnerCO2Density::calculateCO2Density( tableCoords, density ); + calculateCO2Viscosity( tableCoords, density, viscosity ); FunctionManager & functionManager = getGlobalState().getFunctionManager(); m_CO2ViscosityTable = dynamicCast< TableFunction * >( functionManager.createChild( "TableFunction", "CO2ViscosityTable" ) ); - m_CO2ViscosityTable->setTableCoordinates( tableCoords.get() ); + m_CO2ViscosityTable->setTableCoordinates( tableCoords.getCoords() ); m_CO2ViscosityTable->setTableValues( viscosity ); m_CO2ViscosityTable->reInitializeFunction(); m_CO2ViscosityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); @@ -129,20 +97,17 @@ void FenghourCO2Viscosity::fenghourCO2ViscosityFunction( real64 const & temperat viscosity = 1e-6 * (vlimit + vxcess + vcrit); } -void FenghourCO2Viscosity::calculateCO2Viscosity( array1d< array1d< real64 > > const & coordinates, - array1d< real64 > const & valuesDensity, - array1d< real64 > const & valuesViscosity ) +void FenghourCO2Viscosity::calculateCO2Viscosity( PTTableCoordinates const & tableCoords, + array1d< real64 > const & densities, + array1d< real64 > const & viscosities ) { - localIndex const numPressures = coordinates[0].size(); - localIndex const numTemperatures = coordinates[1].size(); - - for( localIndex i = 0; i < numPressures; ++i ) + for( localIndex i = 0; i < tableCoords.nPressures(); ++i ) { - for( localIndex j = 0; j < numTemperatures; ++j ) + for( localIndex j = 0; j < tableCoords.nTemperatures(); ++j ) { - fenghourCO2ViscosityFunction( coordinates[1][j], - valuesDensity[j*numPressures+i], - valuesViscosity[j*numPressures+i] ); + fenghourCO2ViscosityFunction( tableCoords.getTemperature( j ), + densities[j*tableCoords.nPressures()+i], + viscosities[j*tableCoords.nPressures()+i] ); } } } @@ -154,7 +119,7 @@ FenghourCO2Viscosity::KernelWrapper FenghourCO2Viscosity::createKernelWrapper() m_CO2ViscosityTable ); } -REGISTER_CATALOG_ENTRY( PVTFunctionBase, FenghourCO2Viscosity, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) +REGISTER_CATALOG_ENTRY( PVTFunctionBase, FenghourCO2Viscosity, string_array const &, string_array const &, array1d< real64 > const & ) } // end namespace PVTProps diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp index 056ff0542ac..bef04c8d5e3 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp @@ -21,6 +21,7 @@ #include "PVTFunctionBase.hpp" +#include "constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp" #include "managers/Functions/TableFunction.hpp" namespace geosx @@ -78,8 +79,8 @@ class FenghourCO2Viscosity : public PVTFunctionBase { public: - FenghourCO2Viscosity( array1d< string > const & inputPara, - array1d< string > const & componentNames, + FenghourCO2Viscosity( string_array const & inputPara, + string_array const & componentNames, array1d< real64 > const & componentMolarWeight ); ~FenghourCO2Viscosity() override {} @@ -103,11 +104,11 @@ class FenghourCO2Viscosity : public PVTFunctionBase private: - void makeTable( array1d< string > const & inputPara ); + void makeTable( string_array const & inputPara ); - void calculateCO2Viscosity( array1d< array1d< real64 > > const & coordinates, - array1d< real64 > const & valuesDensity, - array1d< real64 > const & valuesViscosity ); + void calculateCO2Viscosity( PVTProps::PTTableCoordinates const & tableCoords, + array1d< real64 > const & density, + array1d< real64 > const & viscosity ); void fenghourCO2ViscosityFunction( real64 const & temperatureCent, real64 const & density, diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp index bea2944b70f..d1522aebd43 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp @@ -28,6 +28,27 @@ namespace constitutive namespace PVTProps { +class PTTableCoordinates +{ +public: + PTTableCoordinates() + { coords.resize( 2 ); } + + localIndex nPressures() const { return coords[0].size(); } + localIndex nTemperatures() const { return coords[1].size(); } + + void appendPressure( const real64 & pres ) { coords[0].emplace_back( pres ); } + void appendTemperature( const real64 & temp ) { coords[1].emplace_back( temp ); } + + real64 const & getPressure( localIndex i ) const { return coords[0][i]; } + real64 const & getTemperature( localIndex i ) const { return coords[1][i]; } + + array1d< array1d< real64 > > const & getCoords() const { return coords; } + +private: + array1d< array1d< real64 > > coords; +}; + struct PVTFunctionHelpers { @@ -49,24 +70,86 @@ struct PVTFunctionHelpers return id; } -}; - -class PTTableCoordinates -{ -public: - PTTableCoordinates() - { coords.resize( 2 ); } - - localIndex nPressures() const { return coords[0].size(); } - localIndex nTemperatures() const { return coords[1].size(); } - - void appendPressure( const real64 & pres ) { coords[0].emplace_back( pres ); } - void appendTemperature( const real64 & temp ) { coords[1].emplace_back( temp ); } + static real64 + initializePropertyTableWithSalinity( string_array const & inputParameters, + PTTableCoordinates & tableCoords ) + { + real64 TStart = -1.0; + real64 TEnd = -1.0; + real64 dT = -1.0; + real64 PStart = -1.0; + real64 PEnd = -1.0; + real64 dP = -1.0; + real64 salinity = -1.0; + + GEOSX_ERROR_IF( inputParameters.size() != 9, "Invalid property input!" ); + + try + { + PStart = stod( inputParameters[2] ); + PEnd = stod( inputParameters[3] ); + dP = stod( inputParameters[4] ); + + TStart = stod( inputParameters[5] ); + TEnd = stod( inputParameters[6] ); + dT = stod( inputParameters[7] ); + + salinity = stod( inputParameters[8] ); + } + catch( const std::invalid_argument & e ) + { + GEOSX_ERROR( "Invalid BrineCO2Density argument:" + string( e.what()) ); + } + + for( real64 P = PStart; P <= PEnd; P += dP ) + { + tableCoords.appendPressure( P ); + } + for( real64 T = TStart; T <= TEnd; T += dT ) + { + tableCoords.appendTemperature( T ); + } + return salinity; + } - array1d< array1d< real64 > > const & get() const { return coords; } + static void + initializePropertyTable( string_array const & inputParameters, + PTTableCoordinates & tableCoords ) + { + real64 TStart = -1.0; + real64 TEnd = -1.0; + real64 dT = -1.0; + real64 PStart = -1.0; + real64 PEnd = -1.0; + real64 dP = -1.0; + + GEOSX_ERROR_IF( inputParameters.size() != 8, "Invalid property input!" ); + + try + { + PStart = stod( inputParameters[2] ); + PEnd = stod( inputParameters[3] ); + dP = stod( inputParameters[4] ); + + TStart = stod( inputParameters[5] ); + TEnd = stod( inputParameters[6] ); + dT = stod( inputParameters[7] ); + } + catch( const std::invalid_argument & e ) + { + GEOSX_ERROR( "Invalid property argument:" + string( e.what()) ); + } + + for( real64 P = PStart; P <= PEnd; P += dP ) + { + tableCoords.appendPressure( P ); + } + for( real64 T = TStart; T <= TEnd; T += dT ) + { + tableCoords.appendTemperature( T ); + } + } -private: - array1d< array1d< real64 > > coords; }; } // namespace PVTProps diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp index 3fff987d77d..64f06866d57 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp @@ -18,7 +18,6 @@ #include "constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp" -#include "constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp" #include "managers/Functions/FunctionManager.hpp" #include "managers/GeosxState.hpp" @@ -140,86 +139,50 @@ real64 f( real64 const & T, } -SpanWagnerCO2Density::SpanWagnerCO2Density( array1d< string > const & inputPara, - array1d< string > const & componentNames, +SpanWagnerCO2Density::SpanWagnerCO2Density( string_array const & inputPara, + string_array const & componentNames, array1d< real64 > const & componentMolarWeight ): PVTFunctionBase( inputPara[1], componentNames, componentMolarWeight ) { - std::vector< string > const expectedCO2ComponentNames( { "CO2", "co2" } ); + char const * expectedCO2ComponentNames[] = { "CO2", "co2" }; m_CO2Index = PVTFunctionHelpers::findName( componentNames, expectedCO2ComponentNames ); GEOSX_ERROR_IF( m_CO2Index < 0 || m_CO2Index >= componentNames.size(), "Component CO2 is not found!" ); makeTable( inputPara ); } -void SpanWagnerCO2Density::makeTable( array1d< string > const & inputPara ) +void SpanWagnerCO2Density::makeTable( string_array const & inputPara ) { - real64 TStart = -1.0; - real64 TEnd = -1.0; - real64 dT = -1.0; - real64 PStart = -1.0; - real64 PEnd = -1.0; - real64 dP = -1.0; - - GEOSX_ERROR_IF( inputPara.size() < 8, "Invalid SpanWagnerCO2Density input!" ); - - try - { - PStart = stod( inputPara[2] ); - PEnd = stod( inputPara[3] ); - dP = stod( inputPara[4] ); - - TStart = stod( inputPara[5] ); - TEnd = stod( inputPara[6] ); - dT = stod( inputPara[7] ); - } - catch( const std::invalid_argument & e ) - { - GEOSX_ERROR( "Invalid SpanWagnerCO2Density argument:" + string( e.what()) ); - } - PTTableCoordinates tableCoords; - for( real64 P = PStart; P <= PEnd; P += dP ) - { - tableCoords.appendPressure( P ); - } - for( real64 T = TStart; T <= TEnd; T += dT ) - { - tableCoords.appendTemperature( T ); - } + PVTFunctionHelpers::initializePropertyTable( inputPara, tableCoords ); - localIndex const nP = tableCoords.nPressures(); - localIndex const nT = tableCoords.nTemperatures(); - array1d< real64 > values( nP * nT ); - calculateCO2Density( tableCoords.get(), values ); + array1d< real64 > densities( tableCoords.nPressures() * tableCoords.nTemperatures() ); + calculateCO2Density( tableCoords, densities ); FunctionManager & functionManager = getGlobalState().getFunctionManager(); m_CO2DensityTable = dynamicCast< TableFunction * >( functionManager.createChild( "TableFunction", "CO2DensityTable" ) ); - m_CO2DensityTable->setTableCoordinates( tableCoords.get() ); - m_CO2DensityTable->setTableValues( values ); + m_CO2DensityTable->setTableCoordinates( tableCoords.getCoords() ); + m_CO2DensityTable->setTableValues( densities ); m_CO2DensityTable->reInitializeFunction(); m_CO2DensityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); } -void SpanWagnerCO2Density::calculateCO2Density( array1d< array1d< real64 > > const & coordinates, - array1d< real64 > const & values ) +void SpanWagnerCO2Density::calculateCO2Density( PTTableCoordinates const & tableCoords, + array1d< real64 > const & densities ) { constexpr real64 TK_f = 273.15; - localIndex const numPressures = coordinates[0].size(); - localIndex const numTemperatures = coordinates[1].size(); - - for( localIndex i = 0; i < numPressures; ++i ) + for( localIndex i = 0; i < tableCoords.nPressures(); ++i ) { - real64 const PPa = coordinates[0][i]; - for( localIndex j = 0; j < numTemperatures; ++j ) + real64 const PPa = tableCoords.getPressure( i ); + for( localIndex j = 0; j < tableCoords.nTemperatures(); ++j ) { - real64 const TK = coordinates[1][j] + TK_f; - spanWagnerCO2DensityFunction( TK, PPa, values[j*numPressures+i], &detail::f ); + real64 const TK = tableCoords.getTemperature( j ) + TK_f; + spanWagnerCO2DensityFunction( TK, PPa, densities[j*tableCoords.nPressures()+i], &detail::f ); } } } @@ -302,7 +265,7 @@ SpanWagnerCO2Density::KernelWrapper SpanWagnerCO2Density::createKernelWrapper() m_CO2Index ); } -REGISTER_CATALOG_ENTRY( PVTFunctionBase, SpanWagnerCO2Density, array1d< string > const &, array1d< string > const &, array1d< real64 > const & ) +REGISTER_CATALOG_ENTRY( PVTFunctionBase, SpanWagnerCO2Density, string_array const &, string_array const &, array1d< real64 > const & ) } // namespace PVTProps diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp index c35155709c2..1db2563cf37 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp @@ -21,6 +21,7 @@ #include "PVTFunctionBase.hpp" +#include "constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp" #include "managers/Functions/TableFunction.hpp" namespace geosx @@ -83,8 +84,8 @@ class SpanWagnerCO2Density : public PVTFunctionBase { public: - SpanWagnerCO2Density( array1d< string > const & inputPara, - array1d< string > const & componentNames, + SpanWagnerCO2Density( string_array const & inputPara, + string_array const & componentNames, array1d< real64 > const & componentMolarWeight ); ~SpanWagnerCO2Density() override {} @@ -108,12 +109,12 @@ class SpanWagnerCO2Density : public PVTFunctionBase KernelWrapper createKernelWrapper(); static - void calculateCO2Density( array1d< array1d< real64 > > const & coordinates, - array1d< real64 > const & values ); + void calculateCO2Density( PVTProps::PTTableCoordinates const & tableCoords, + array1d< real64 > const & densities ); private: - void makeTable( array1d< string > const & inputPara ); + void makeTable( string_array const & inputPara ); static void spanWagnerCO2DensityFunction( real64 const & T, diff --git a/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp b/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp index 0fda2b86d90..48aeba06f30 100644 --- a/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp +++ b/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp @@ -37,13 +37,13 @@ using namespace geosx::constitutive::PVTProps; /// Input tables written into temporary files during testing -static const char * PVTLiquidString = "DensityFun BrineCO2Density 1e6 1.5e7 5e4 94 96 1 0.2\n" - "ViscosityFun BrineViscosity 0.1"; +static const char * pvtLiquidTableContent = "DensityFun BrineCO2Density 1e6 1.5e7 5e4 94 96 1 0.2\n" + "ViscosityFun BrineViscosity 0.1"; -static const char * PVTGasString = "DensityFun SpanWagnerCO2Density 1e6 1.5e7 5e4 94 96 1\n" - "ViscosityFun FenghourCO2Viscosity 1e6 1.5e7 5e4 94 96 1"; +static const char * pvtGasTableContent = "DensityFun SpanWagnerCO2Density 1e6 1.5e7 5e4 94 96 1\n" + "ViscosityFun FenghourCO2Viscosity 1e6 1.5e7 5e4 94 96 1"; -static const char * CO2FlashString = "FlashModel CO2Solubility 1e6 1.5e7 5e4 94 96 1 0.15"; +static const char * co2FlashTableContent = "FlashModel CO2Solubility 1e6 1.5e7 5e4 94 96 1 0.15"; void testValuesAgainstPreviousImplementation( PVTFunctionBaseUpdate const & pvtFunctionWrapper, real64 const pressure, @@ -322,7 +322,7 @@ std::unique_ptr< MODEL > makePVTFunction( string const & filename, string const & key ) { // define component names and molar weight - array1d< string > componentNames; + string_array componentNames; componentNames.resize( 2 ); componentNames[0] = "co2"; componentNames[1] = "water"; @@ -361,12 +361,12 @@ std::unique_ptr< MODEL > makeFlashModel( string const & filename, string const & key ) { // define phase names - array1d< string > phaseNames; + string_array phaseNames; phaseNames.resize( 2 ); phaseNames[0] = "gas"; phaseNames[1] = "liquid"; // define component names and molar weight - array1d< string > componentNames; + string_array componentNames; componentNames.resize( 2 ); componentNames[0] = "co2"; componentNames[1] = "water"; @@ -407,7 +407,7 @@ class BrineViscosityTest : public ::testing::Test public: BrineViscosityTest() { - writeTableToFile( filename, PVTLiquidString ); + writeTableToFile( filename, pvtLiquidTableContent ); pvtFunction = makePVTFunction< BrineViscosity >( filename, key ); } @@ -465,7 +465,7 @@ class FenghourCO2ViscosityTest : public ::testing::Test public: FenghourCO2ViscosityTest() { - writeTableToFile( filename, PVTGasString ); + writeTableToFile( filename, pvtGasTableContent ); pvtFunction = makePVTFunction< FenghourCO2Viscosity >( filename, key ); } @@ -524,7 +524,7 @@ class BrineCO2DensityTest : public ::testing::Test public: BrineCO2DensityTest() { - writeTableToFile( filename, PVTLiquidString ); + writeTableToFile( filename, pvtLiquidTableContent ); pvtFunction = makePVTFunction< BrineCO2Density >( filename, key ); } @@ -624,7 +624,7 @@ class SpanWagnerCO2DensityTest : public ::testing::Test public: SpanWagnerCO2DensityTest() { - writeTableToFile( filename, PVTGasString ); + writeTableToFile( filename, pvtGasTableContent ); pvtFunction = makePVTFunction< SpanWagnerCO2Density >( filename, key ); } @@ -721,7 +721,7 @@ class CO2SolubilityTest : public ::testing::Test public: CO2SolubilityTest() { - writeTableToFile( filename, CO2FlashString ); + writeTableToFile( filename, co2FlashTableContent ); flashModel = makeFlashModel< CO2Solubility >( filename, key ); } diff --git a/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp b/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp index 01f6b8a3ea1..dc1b7e43b47 100644 --- a/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp +++ b/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp @@ -35,91 +35,91 @@ using namespace geosx::constitutive::PVTProps; /// Black-oil tables written into temporary files during testing -static const char * PVTGString = "#\tPg(Pa)\t\tRv(sm3/sm3)\tBg(m3/sm3)\tVisc(Pa.s)\n" - "\n" - "\t3000000\t\t0.000132\t0.04234\t 0.00001344\n" - "\t\t\t\t0\t\t\t0.04231\t 0.00001389\n" - "\t6000000\t\t0.000124\t0.02046\t 0.0000142\n" - "\t\t\t\t0\t\t\t0.02043\t 0.0000145\n" - "\t9000000\t\t0.000126\t0.01328\t 0.00001526\n" - "\t\t\t\t0\t\t\t0.01325\t 0.00001532\n" - " 12000000\t\t0.000135\t0.00977\t 0.0000166\n" - "\t\t\t\t0\t\t\t0.00973\t 0.00001634\n" - " 15000000\t\t0.000149\t0.00773\t 0.00001818\n" - "\t\t\t\t0\t\t\t0.00769\t 0.00001752\n" - " 18000000\t\t0.000163\t0.006426\t0.00001994\n" - "\t\t\t\t0\t\t\t0.006405\t0.00001883\n" - " 21000000\t\t0.000191\t0.005541\t0.00002181\n" - "\t\t\t\t0\t\t\t0.005553\t0.00002021\n" - " 24000000\t\t0.000225\t0.004919\t0.0000237\n" - "\t\t\t\t0\t\t\t0.004952\t0.00002163\n" - " 27000000\t\t0.000272\t0.004471\t0.00002559\n" - "\t\t\t\t0\t\t\t0.004511\t0.00002305\n" - " 29500000\t\t0.000354\t0.004194\t0.00002714\n" - "\t\t\t\t0\t\t\t0.004225\t0.00002423\n" - " 31000000\t\t0.000403\t0.004031\t0.00002806\n" - "\t\t\t\t0.000354\t0.004059\t0.00002768\n" - " 33000000\t\t0.000354\t0.00391\t 0.00002832\n" - "\t\t\t\t0\t\t\t0.003913\t0.00002583\n" - " 53000000\t\t0.000479\t0.003868\t0.00002935\n" - "\t\t\t\t0.000354\t0.0039\t\t0.00002842\n" - "\t\t\t\t0\t\t\t0.003903\t0.00002593"; - -static const char * PVTOString = "# Rs[sm3/sm3]\tPbub[Pa]\tBo[m3/sm3]\tVisc(Pa.s)\n" - "\n" - " 2\t 2000000\t 1.02\t 0.000975\n" - " 5\t 5000000\t 1.03\t 0.00091\n" - " 10\t 10000000\t1.04\t 0.00083\n" - " 15\t 20000000\t1.05\t 0.000695\n" - " 90000000\t1.03\t 0.000985 -- some line comment\n" - " 30\t 30000000\t1.07\t 0.000594\n" - " 40\t 40000000\t1.08\t 0.00051\n" - " 50000000\t1.07\t 0.000549 -- another one\n" - " 90000000\t1.06\t 0.00074\n" - " 50\t 50000000.7\t1.09\t 0.000449\n" - " 90000000.7\t1.08\t 0.000605"; - -static const char * PVTWString = "#\tPref[bar]\tBw[m3/sm3]\tCp[1/bar]\t Visc[cP]\n" - "\t30600000.1\t1.03\t\t0.00000000041\t0.0003"; +static const char * pvtgTableContent = "#\tPg(Pa)\t\tRv(sm3/sm3)\tBg(m3/sm3)\tVisc(Pa.s)\n" + "\n" + "\t3000000\t\t0.000132\t0.04234\t 0.00001344\n" + "\t\t\t\t0\t\t\t0.04231\t 0.00001389\n" + "\t6000000\t\t0.000124\t0.02046\t 0.0000142\n" + "\t\t\t\t0\t\t\t0.02043\t 0.0000145\n" + "\t9000000\t\t0.000126\t0.01328\t 0.00001526\n" + "\t\t\t\t0\t\t\t0.01325\t 0.00001532\n" + " 12000000\t\t0.000135\t0.00977\t 0.0000166\n" + "\t\t\t\t0\t\t\t0.00973\t 0.00001634\n" + " 15000000\t\t0.000149\t0.00773\t 0.00001818\n" + "\t\t\t\t0\t\t\t0.00769\t 0.00001752\n" + " 18000000\t\t0.000163\t0.006426\t0.00001994\n" + "\t\t\t\t0\t\t\t0.006405\t0.00001883\n" + " 21000000\t\t0.000191\t0.005541\t0.00002181\n" + "\t\t\t\t0\t\t\t0.005553\t0.00002021\n" + " 24000000\t\t0.000225\t0.004919\t0.0000237\n" + "\t\t\t\t0\t\t\t0.004952\t0.00002163\n" + " 27000000\t\t0.000272\t0.004471\t0.00002559\n" + "\t\t\t\t0\t\t\t0.004511\t0.00002305\n" + " 29500000\t\t0.000354\t0.004194\t0.00002714\n" + "\t\t\t\t0\t\t\t0.004225\t0.00002423\n" + " 31000000\t\t0.000403\t0.004031\t0.00002806\n" + "\t\t\t\t0.000354\t0.004059\t0.00002768\n" + " 33000000\t\t0.000354\t0.00391\t 0.00002832\n" + "\t\t\t\t0\t\t\t0.003913\t0.00002583\n" + " 53000000\t\t0.000479\t0.003868\t0.00002935\n" + "\t\t\t\t0.000354\t0.0039\t\t0.00002842\n" + "\t\t\t\t0\t\t\t0.003903\t0.00002593"; + +static const char * pvtoTableContent = "# Rs[sm3/sm3]\tPbub[Pa]\tBo[m3/sm3]\tVisc(Pa.s)\n" + "\n" + " 2\t 2000000\t 1.02\t 0.000975\n" + " 5\t 5000000\t 1.03\t 0.00091\n" + " 10\t 10000000\t1.04\t 0.00083\n" + " 15\t 20000000\t1.05\t 0.000695\n" + " 90000000\t1.03\t 0.000985 -- some line comment\n" + " 30\t 30000000\t1.07\t 0.000594\n" + " 40\t 40000000\t1.08\t 0.00051\n" + " 50000000\t1.07\t 0.000549 -- another one\n" + " 90000000\t1.06\t 0.00074\n" + " 50\t 50000000.7\t1.09\t 0.000449\n" + " 90000000.7\t1.08\t 0.000605"; + +static const char * pvtwTableContent = "#\tPref[bar]\tBw[m3/sm3]\tCp[1/bar]\t Visc[cP]\n" + "\t30600000.1\t1.03\t\t0.00000000041\t0.0003"; /// Dead-oil tables written into temporary files during testing -static const char * PVDGString = "# Pg(Pa) Bg(m3/sm3) Visc(Pa.s)\n" - "3000000 0.04234 0.00001344\n" - "6000000 0.02046 0.0000142\n" - "9000000 0.01328 0.00001526\n" - "12000000 0.00977 0.0000166\n" - "15000000 0.00773 0.00001818\n" - "18000000 0.006426 0.00001994\n" - "21000000 0.005541 0.00002181\n" - "24000000 0.004919 0.0000237\n" - "27000000 0.004471 0.00002559\n" - "29500000 0.004194 0.00002714\n" - "31000000 0.004031 0.00002806\n" - "33000000 0.00391 0.00002832\n" - "53000000 0.003868 0.00002935"; - -static const char * PVDOString = "#P[Pa] Bo[m3/sm3] Visc(Pa.s)\n" - "2000000 1.02 0.000975\n" - "5000000 1.03 0.00091\n" - "10000000 1.04 0.00083\n" - "20000000 1.05 0.000695\n" - "30000000 1.07 0.000594\n" - "40000000 1.08 0.00051\n" - "50000000.7 1.09 0.000449"; - -static const char * PVDWString = "# Pref[bar] Bw[m3/sm3] Cp[1/bar] Visc[cP]\n" - " 30600000.1 1.03 0.00000000041 0.0003"; +static const char * pvdgTableContent = "# Pg(Pa) Bg(m3/sm3) Visc(Pa.s)\n" + "3000000 0.04234 0.00001344\n" + "6000000 0.02046 0.0000142\n" + "9000000 0.01328 0.00001526\n" + "12000000 0.00977 0.0000166\n" + "15000000 0.00773 0.00001818\n" + "18000000 0.006426 0.00001994\n" + "21000000 0.005541 0.00002181\n" + "24000000 0.004919 0.0000237\n" + "27000000 0.004471 0.00002559\n" + "29500000 0.004194 0.00002714\n" + "31000000 0.004031 0.00002806\n" + "33000000 0.00391 0.00002832\n" + "53000000 0.003868 0.00002935"; + +static const char * pvdoTableContent = "#P[Pa] Bo[m3/sm3] Visc(Pa.s)\n" + "2000000 1.02 0.000975\n" + "5000000 1.03 0.00091\n" + "10000000 1.04 0.00083\n" + "20000000 1.05 0.000695\n" + "30000000 1.07 0.000594\n" + "40000000 1.08 0.00051\n" + "50000000.7 1.09 0.000449"; + +static const char * pvdwTableContent = "# Pref[bar] Bw[m3/sm3] Cp[1/bar] Visc[cP]\n" + " 30600000.1 1.03 0.00000000041 0.0003"; // CO2-brine model -static const char * PVTLiquidString = "DensityFun BrineCO2Density 1e6 1.5e7 5e4 94 96 1 0.2\n" - "ViscosityFun BrineViscosity 0.1"; +static const char * pvtLiquidTableContent = "DensityFun BrineCO2Density 1e6 1.5e7 5e4 94 96 1 0.2\n" + "ViscosityFun BrineViscosity 0.1"; -static const char * PVTGasString = "DensityFun SpanWagnerCO2Density 1e6 1.5e7 5e4 94 96 1\n" - "ViscosityFun FenghourCO2Viscosity 1e6 1.5e7 5e4 94 96 1"; +static const char * pvtGasTableContent = "DensityFun SpanWagnerCO2Density 1e6 1.5e7 5e4 94 96 1\n" + "ViscosityFun FenghourCO2Viscosity 1e6 1.5e7 5e4 94 96 1"; -static const char * CO2FlashString = "FlashModel CO2Solubility 1e6 1.5e7 5e4 94 96 1 0.15"; +static const char * co2FlashTableContent = "FlashModel CO2Solubility 1e6 1.5e7 5e4 94 96 1 0.15"; void testNumericalDerivatives( MultiFluidBase & fluid, Group & parent, @@ -656,9 +656,9 @@ class LiveOilFluidTest : public CompositionalFluidTestBase public: LiveOilFluidTest() { - writeTableToFile( "pvto.txt", PVTOString ); - writeTableToFile( "pvtg.txt", PVTGString ); - writeTableToFile( "pvtw.txt", PVTWString ); + writeTableToFile( "pvto.txt", pvtoTableContent ); + writeTableToFile( "pvtg.txt", pvtgTableContent ); + writeTableToFile( "pvtw.txt", pvtwTableContent ); parent.resize( 1 ); fluid = &makeLiveOilFluid( "fluid", &parent ); @@ -714,9 +714,9 @@ class DeadOilFluidTest : public CompositionalFluidTestBase DeadOilFluidTest() { - writeTableToFile( "pvdo.txt", PVDOString ); - writeTableToFile( "pvdg.txt", PVDGString ); - writeTableToFile( "pvdw.txt", PVDWString ); + writeTableToFile( "pvdo.txt", pvdoTableContent ); + writeTableToFile( "pvdg.txt", pvdgTableContent ); + writeTableToFile( "pvdw.txt", pvdwTableContent ); parent.resize( 1 ); fluid = &makeDeadOilFluid( "fluid", &parent ); @@ -835,9 +835,9 @@ class MultiPhaseMultiComponentFluidTest : public CompositionalFluidTestBase MultiPhaseMultiComponentFluidTest() { - writeTableToFile( "pvtliquid.txt", PVTLiquidString ); - writeTableToFile( "pvtgas.txt", PVTGasString ); - writeTableToFile( "co2flash.txt", CO2FlashString ); + writeTableToFile( "pvtliquid.txt", pvtLiquidTableContent ); + writeTableToFile( "pvtgas.txt", pvtGasTableContent ); + writeTableToFile( "co2flash.txt", co2FlashTableContent ); parent.resize( 1 ); fluid = &makeMultiPhaseMultiComponentFluid( "fluid", &parent ); From ef9869e149dc79dc32843b74ea8bb3b32edd253c Mon Sep 17 00:00:00 2001 From: Francois Hamon Date: Thu, 11 Mar 2021 18:44:21 -0800 Subject: [PATCH 07/10] implemented Sergey's suggestion; addressed Thomas' comments --- .../fluid/MultiPhaseMultiComponentFluid.cpp | 173 ++++--- .../fluid/MultiPhaseMultiComponentFluid.hpp | 457 +++++++++--------- .../PVTFunctions/BrineCO2DensityFunction.cpp | 17 +- .../PVTFunctions/CO2SolubilityFunction.cpp | 37 +- .../FenghourCO2ViscosityFunction.cpp | 15 +- .../fluid/PVTFunctions/FlashModelBase.hpp | 10 +- .../fluid/PVTFunctions/PVTFunctionHelpers.hpp | 97 ++-- .../SpanWagnerCO2DensityFunction.cpp | 16 +- .../constitutive/fluid/multiFluidSelector.hpp | 4 +- .../constitutive/unitTests/testMultiFluid.cpp | 25 +- ...tiComponentFluid.rst => CO2BrineFluid.rst} | 0 ...luid_other.rst => CO2BrineFluid_other.rst} | 0 .../fileIO/schema/docs/Constitutive.rst | 2 +- .../fileIO/schema/docs/Constitutive_other.rst | 2 +- src/coreComponents/fileIO/schema/schema.xsd | 30 +- .../fileIO/schema/schema.xsd.other | 106 ++-- .../co2_flux_3d.xml | 2 +- .../co2_hybrid_1d.xml | 2 +- .../staircase_co2_wells_3d.xml | 2 +- .../staircase_co2_wells_hybrid_3d.xml | 2 +- .../FieldCaseCo2InjTutorial.xml | 2 +- src/docs/sphinx/CompleteXMLSchema.rst | 28 +- 22 files changed, 571 insertions(+), 458 deletions(-) rename src/coreComponents/fileIO/schema/docs/{MultiPhaseMultiComponentFluid.rst => CO2BrineFluid.rst} (100%) rename src/coreComponents/fileIO/schema/docs/{MultiPhaseMultiComponentFluid_other.rst => CO2BrineFluid_other.rst} (100%) diff --git a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp index 52ebcba7f64..0150dca803c 100644 --- a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp +++ b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp @@ -33,65 +33,113 @@ namespace constitutive using namespace PVTProps; -MultiPhaseMultiComponentFluid::MultiPhaseMultiComponentFluid( string const & name, Group * const parent ): - MultiFluidBase( name, parent ) +namespace { - registerWrapper( viewKeyStruct::phasePVTParaFilesString(), &m_phasePVTParaFiles ). - setInputFlag( InputFlags::REQUIRED ). - setRestartFlags( RestartFlags::NO_WRITE ). - setDescription( "Names of the files defining the parameters of the viscosity and density models" ); - - registerWrapper( viewKeyStruct::flashModelParaFileString(), &m_flashModelParaFile ). - setInputFlag( InputFlags::REQUIRED ). - setRestartFlags( RestartFlags::NO_WRITE ). - setDescription( "Name of the file defining the parameters of the flash model" ); +template< typename P1DENS, typename P1VISC, typename P2DENS, typename P2VISC, typename FLASH > class + TwoPhaseCatalogNames {}; + +template<> class + TwoPhaseCatalogNames< PVTProps::BrineCO2Density, + PVTProps::BrineViscosity, + PVTProps::SpanWagnerCO2Density, + PVTProps::FenghourCO2Viscosity, + PVTProps::CO2Solubility > +{ +public: + static string name() { return "CO2BrineFluid"; } +}; +} // end namespace + +// provide a definition for catalogName() +template< typename P1DENS, typename P1VISC, typename P2DENS, typename P2VISC, typename FLASH > +string MultiPhaseMultiComponentFluid< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >::catalogName() +{ + return TwoPhaseCatalogNames< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >::name(); } -MultiPhaseMultiComponentFluid::~MultiPhaseMultiComponentFluid() -{} - - +// explicit instantiation of the model template; unfortunately we can't use CO2BrineFluid alias for this +template class MultiPhaseMultiComponentFluid< PVTProps::BrineCO2Density, + PVTProps::BrineViscosity, + PVTProps::SpanWagnerCO2Density, + PVTProps::FenghourCO2Viscosity, + PVTProps::CO2Solubility >; + +// template< typename P1DENS, typename P1VISC, typename P2DENS, typename P2VISC, typename FLASH > +// MultiPhaseMultiComponentFluid< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >:: +// MultiPhaseMultiComponentFluid( string const & name, Group * const parent ): +// MultiFluidBase( name, parent ) +// { +// registerWrapper( viewKeyStruct::phasePVTParaFilesString(), &m_phasePVTParaFiles ). +// setInputFlag( InputFlags::REQUIRED ). +// setRestartFlags( RestartFlags::NO_WRITE ). +// setDescription( "Names of the files defining the parameters of the viscosity and density models" ); + +// registerWrapper( viewKeyStruct::flashModelParaFileString(), &m_flashModelParaFile ). +// setInputFlag( InputFlags::REQUIRED ). +// setRestartFlags( RestartFlags::NO_WRITE ). +// setDescription( "Name of the file defining the parameters of the flash model" ); +// } + +// template< typename P1DENS, typename P1VISC, typename P2DENS, typename P2VISC, typename FLASH > +// MultiPhaseMultiComponentFluid< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >:: +// ~MultiPhaseMultiComponentFluid() +// {} + +template< typename P1DENS, typename P1VISC, typename P2DENS, typename P2VISC, typename FLASH > std::unique_ptr< ConstitutiveBase > -MultiPhaseMultiComponentFluid::deliverClone( string const & name, - Group * const parent ) const +MultiPhaseMultiComponentFluid< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >:: +deliverClone( string const & name, Group * const parent ) const { std::unique_ptr< ConstitutiveBase > clone = MultiFluidBase::deliverClone( name, parent ); MultiPhaseMultiComponentFluid * const newConstitutiveRelation = dynamic_cast< MultiPhaseMultiComponentFluid * >(clone.get()); - newConstitutiveRelation->m_phaseGasIndex = this->m_phaseGasIndex; - newConstitutiveRelation->m_phaseLiquidIndex = this->m_phaseLiquidIndex; + newConstitutiveRelation->m_p1Index = this->m_p1Index; + newConstitutiveRelation->m_p2Index = this->m_p2Index; newConstitutiveRelation->createPVTModels(); return clone; } -void MultiPhaseMultiComponentFluid::postProcessInput() +template< typename P1DENS, typename P1VISC, typename P2DENS, typename P2VISC, typename FLASH > +void MultiPhaseMultiComponentFluid< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >::postProcessInput() { MultiFluidBase::postProcessInput(); localIndex const numPhases = numFluidPhases(); localIndex const numComps = numFluidComponents(); - GEOSX_ERROR_IF( numPhases != 2, "The number of phases in this model should be equal to 2" ); - GEOSX_ERROR_IF( numComps != 2, "The number of components in this model should be equal to 2" ); - GEOSX_ERROR_IF( m_phasePVTParaFiles.size() != 2, "The number of phasePVTParaFiles is not the same as the number of phases!" ); - - char const * expectedGasPhaseNames[] = { "CO2", "co2", "gas", "Gas" }; - m_phaseGasIndex = PVTFunctionHelpers::findName( m_phaseNames, - expectedGasPhaseNames ); - GEOSX_ERROR_IF( m_phaseGasIndex < 0 || m_phaseGasIndex >= m_phaseNames.size(), - "Phase co2/gas is not found!" ); + GEOSX_THROW_IF( numPhases != 2, + "The number of phases in this model should be equal to 2", + InputError ); + GEOSX_THROW_IF( numComps != 2, + "The number of components in this model should be equal to 2", + InputError ); + GEOSX_THROW_IF( m_phasePVTParaFiles.size() != 2, + "The number of phasePVTParaFiles is not the same as the number of phases!", + InputError ); + + // NOTE: for now, the names of the phases are still hardcoded here + // Later, we could read them from the XML file and we would then have a general class here char const * expectedWaterPhaseNames[] = { "Water", "water", "Liquid", "liquid" }; - m_phaseLiquidIndex = PVTFunctionHelpers::findName( m_phaseNames, - expectedWaterPhaseNames ); - GEOSX_ERROR_IF( m_phaseLiquidIndex < 0 || m_phaseLiquidIndex >= m_phaseNames.size(), - "Phase water/liquid is not found!" ); + m_p1Index = PVTFunctionHelpers::findName( m_phaseNames, + expectedWaterPhaseNames ); + GEOSX_THROW_IF( m_p1Index < 0 || m_p1Index >= m_phaseNames.size(), + "Phase water/liquid is not found!", + InputError ); + + char const * expectedGasPhaseNames[] = { "CO2", "co2", "gas", "Gas" }; + m_p2Index = PVTFunctionHelpers::findName( m_phaseNames, + expectedGasPhaseNames ); + GEOSX_THROW_IF( m_p2Index < 0 || m_p2Index >= m_phaseNames.size(), + "Phase co2/gas is not found!", + InputError ); createPVTModels(); } -void MultiPhaseMultiComponentFluid::createPVTModels() +template< typename P1DENS, typename P1VISC, typename P2DENS, typename P2VISC, typename FLASH > +void MultiPhaseMultiComponentFluid< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >::createPVTModels() { // 1) Create the viscosity and density models for( string const & filename : m_phasePVTParaFiles ) @@ -100,6 +148,9 @@ void MultiPhaseMultiComponentFluid::createPVTModels() constexpr std::streamsize buf_size = 256; char buf[buf_size]; + // NOTE: for now, the names of the models are still hardcoded here + // Later, we could read them from the XML file and we would then have a general class here + while( is.getline( buf, buf_size ) ) { string const str( buf ); @@ -107,42 +158,50 @@ void MultiPhaseMultiComponentFluid::createPVTModels() if( strs[0] == "DensityFun" ) { - if( strs[1] == "SpanWagnerCO2Density" ) + if( strs[1] == "BrineCO2Density" ) { - m_co2Density = std::make_unique< SpanWagnerCO2Density >( strs, m_componentNames, m_componentMolarWeight ); - m_co2DensityWrapper.emplace_back( m_co2Density->createKernelWrapper() ); + m_p1Density = std::make_unique< P1DENS >( strs, m_componentNames, m_componentMolarWeight ); + m_p1DensityWrapper.emplace_back( m_p1Density->createKernelWrapper() ); } - else if( strs[1] == "BrineCO2Density" ) + else if( strs[1] == "SpanWagnerCO2Density" ) { - m_brineDensity = std::make_unique< BrineCO2Density >( strs, m_componentNames, m_componentMolarWeight ); - m_brineDensityWrapper.emplace_back( m_brineDensity->createKernelWrapper() ); + m_p2Density = std::make_unique< P2DENS >( strs, m_componentNames, m_componentMolarWeight ); + m_p2DensityWrapper.emplace_back( m_p2Density->createKernelWrapper() ); } } else if( strs[0] == "ViscosityFun" ) { - if( strs[1] == "FenghourCO2Viscosity" ) + if( strs[1] == "BrineViscosity" ) { - m_co2Viscosity = std::make_unique< FenghourCO2Viscosity >( strs, m_componentNames, m_componentMolarWeight ); - m_co2ViscosityWrapper.emplace_back( m_co2Viscosity->createKernelWrapper() ); + m_p1Viscosity = std::make_unique< P1VISC >( strs, m_componentNames, m_componentMolarWeight ); + m_p1ViscosityWrapper.emplace_back( m_p1Viscosity->createKernelWrapper() ); } - else if( strs[1] == "BrineViscosity" ) + else if( strs[1] == "FenghourCO2Viscosity" ) { - m_brineViscosity = std::make_unique< BrineViscosity >( strs, m_componentNames, m_componentMolarWeight ); - m_brineViscosityWrapper.emplace_back( m_brineViscosity->createKernelWrapper() ); + m_p2Viscosity = std::make_unique< P2VISC >( strs, m_componentNames, m_componentMolarWeight ); + m_p2ViscosityWrapper.emplace_back( m_p2Viscosity->createKernelWrapper() ); } } else { - GEOSX_ERROR( "Error: Invalid PVT function: " << strs[0] << "." ); + GEOSX_THROW( "Error: Invalid PVT function: " << strs[0] << ".", InputError ); } } is.close(); } - GEOSX_ERROR_IF( m_co2Density == nullptr, "SpanWagnerCO2Density model not found" ); - GEOSX_ERROR_IF( m_brineDensity == nullptr, "BrineCO2Density model not found" ); - GEOSX_ERROR_IF( m_co2Viscosity == nullptr, "FenghourCO2Viscosity model not found" ); - GEOSX_ERROR_IF( m_brineViscosity == nullptr, "BrineViscosity model not found" ); + GEOSX_THROW_IF( m_p1Density == nullptr, + "BrineCO2Density model not found", + InputError ); + GEOSX_THROW_IF( m_p2Density == nullptr, + "SpanWagnerCO2Density model not found", + InputError ); + GEOSX_THROW_IF( m_p1Viscosity == nullptr, + "BrineViscosity model not found", + InputError ); + GEOSX_THROW_IF( m_p2Viscosity == nullptr, + "FenghourCO2Viscosity model not found", + InputError ); // 2) Create the flash model { @@ -156,21 +215,23 @@ void MultiPhaseMultiComponentFluid::createPVTModels() string_array const strs = stringutilities::tokenize( str, " " ); if( strs[0] == "FlashModel" && strs[1] == "CO2Solubility" ) { - m_co2Solubility = std::make_unique< CO2Solubility >( strs, m_phaseNames, m_componentNames, m_componentMolarWeight ); - m_co2SolubilityWrapper.emplace_back( m_co2Solubility->createKernelWrapper() ); + m_flash = std::make_unique< FLASH >( strs, m_phaseNames, m_componentNames, m_componentMolarWeight ); + m_flashWrapper.emplace_back( m_flash->createKernelWrapper() ); } else { - GEOSX_ERROR( "Error: Invalid flash model: " << strs[0] << ", " << strs[1] << "." ); + GEOSX_THROW( "Error: Invalid flash model: " << strs[0] << ", " << strs[1] << ".", InputError ); } } is.close(); } - GEOSX_ERROR_IF( m_co2Solubility == nullptr, "CO2Solubility model not found" ); + GEOSX_THROW_IF( m_flash == nullptr, + "CO2Solubility model not found", + InputError ); } -REGISTER_CATALOG_ENTRY( ConstitutiveBase, MultiPhaseMultiComponentFluid, string const &, Group * const ) +REGISTER_CATALOG_ENTRY( ConstitutiveBase, CO2BrineFluid, string const &, Group * const ) } //namespace constitutive diff --git a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp index 86dc36eda56..8a6985744e4 100644 --- a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp +++ b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp @@ -38,22 +38,18 @@ namespace constitutive /** * @brief Kernel wrapper class for MultiPhaseMultiComponentFluid. */ -template< typename BRINEVISCWRAPPER, - typename CO2VISCWRAPPER, - typename BRINEDENSWRAPPER, - typename CO2DENSWRAPPER, - typename FLASHWRAPPER > +template< typename P1DENSWRAPPER, typename P1VISCWRAPPER, typename P2DENSWRAPPER, typename P2VISCWRAPPER, typename FLASHWRAPPER > class MultiPhaseMultiComponentFluidUpdate final : public MultiFluidBaseUpdate { public: - MultiPhaseMultiComponentFluidUpdate( localIndex const phaseGasIndex, - localIndex const phaseLiquidIndex, - arrayView1d< BRINEVISCWRAPPER const > const & brineViscosityWrapper, - arrayView1d< CO2VISCWRAPPER const > const & co2ViscosityWrapper, - arrayView1d< BRINEDENSWRAPPER const > const & brineDensityWrapper, - arrayView1d< CO2DENSWRAPPER const > const & co2DensityWrapper, - arrayView1d< FLASHWRAPPER const > const & co2SolubilityWrapper, + MultiPhaseMultiComponentFluidUpdate( localIndex const p1Index, + localIndex const p2Index, + arrayView1d< P1DENSWRAPPER const > const & p1DensityWrapper, + arrayView1d< P1VISCWRAPPER const > const & p1ViscosityWrapper, + arrayView1d< P2DENSWRAPPER const > const & p2DensityWrapper, + arrayView1d< P2VISCWRAPPER const > const & p2ViscosityWrapper, + arrayView1d< FLASHWRAPPER const > const & flashWrapper, arrayView1d< real64 const > const & componentMolarWeight, bool useMass, arrayView3d< real64 > const & phaseFraction, @@ -106,13 +102,13 @@ class MultiPhaseMultiComponentFluidUpdate final : public MultiFluidBaseUpdate dTotalDensity_dPressure, dTotalDensity_dTemperature, dTotalDensity_dGlobalCompFraction ), - m_phaseGasIndex( phaseGasIndex ), - m_phaseLiquidIndex( phaseLiquidIndex ), - m_brineViscosityWrapper( brineViscosityWrapper ), - m_co2ViscosityWrapper( co2ViscosityWrapper ), - m_brineDensityWrapper( brineDensityWrapper ), - m_co2DensityWrapper( co2DensityWrapper ), - m_co2SolubilityWrapper( co2SolubilityWrapper ) + m_p1Index( p1Index ), + m_p2Index( p2Index ), + m_p1DensityWrapper( p1DensityWrapper ), + m_p1ViscosityWrapper( p1ViscosityWrapper ), + m_p2DensityWrapper( p2DensityWrapper ), + m_p2ViscosityWrapper( p2ViscosityWrapper ), + m_flashWrapper( flashWrapper ) {} /// Default copy constructor @@ -208,28 +204,29 @@ class MultiPhaseMultiComponentFluidUpdate final : public MultiFluidBaseUpdate private: - /// Index of the gas phase - localIndex const m_phaseGasIndex; - /// Index of the liquid phase - localIndex const m_phaseLiquidIndex; + localIndex const m_p1Index; - /// Kernel wrapper for brine viscosity updates - arrayView1d< BRINEVISCWRAPPER const > const m_brineViscosityWrapper; - - /// Kernel wrapper for CO2 viscosity updates - arrayView1d< CO2VISCWRAPPER const > const m_co2ViscosityWrapper; + /// Index of the gas phase + localIndex const m_p2Index; /// Kernel wrapper for brine density updates - arrayView1d< BRINEDENSWRAPPER const > const m_brineDensityWrapper; + arrayView1d< P1DENSWRAPPER const > const m_p1DensityWrapper; + + /// Kernel wrapper for brine viscosity updates + arrayView1d< P1VISCWRAPPER const > const m_p1ViscosityWrapper; /// Kernel wrapper for CO2 density updates - arrayView1d< CO2DENSWRAPPER const > const m_co2DensityWrapper; + arrayView1d< P2DENSWRAPPER const > const m_p2DensityWrapper; + + /// Kernel wrapper for CO2 viscosity updates + arrayView1d< P2VISCWRAPPER const > const m_p2ViscosityWrapper; /// Kernel wrapper for phase fraction and phase component fraction updates - arrayView1d< FLASHWRAPPER const > const m_co2SolubilityWrapper; + arrayView1d< FLASHWRAPPER const > const m_flashWrapper; }; +template< typename P1DENS, typename P1VISC, typename P2DENS, typename P2VISC, typename FLASH > class MultiPhaseMultiComponentFluid : public MultiFluidBase { public: @@ -238,23 +235,23 @@ class MultiPhaseMultiComponentFluid : public MultiFluidBase MultiPhaseMultiComponentFluid( string const & name, Group * const parent ); - virtual ~MultiPhaseMultiComponentFluid() override; + virtual ~MultiPhaseMultiComponentFluid() override {}; virtual std::unique_ptr< ConstitutiveBase > deliverClone( string const & name, Group * const parent ) const override; - static string catalogName() { return "MultiPhaseMultiComponentFluid"; } + static string catalogName(); virtual string getCatalogName() const override { return catalogName(); } /// Type of kernel wrapper for in-kernel update - using KernelWrapper = MultiPhaseMultiComponentFluidUpdate< PVTProps::BrineViscosity::KernelWrapper, - PVTProps::FenghourCO2Viscosity::KernelWrapper, - PVTProps::BrineCO2Density::KernelWrapper, - PVTProps::SpanWagnerCO2Density::KernelWrapper, - PVTProps::CO2Solubility::KernelWrapper >; + using KernelWrapper = MultiPhaseMultiComponentFluidUpdate< typename P1DENS::KernelWrapper, + typename P1VISC::KernelWrapper, + typename P2DENS::KernelWrapper, + typename P2VISC::KernelWrapper, + typename FLASH::KernelWrapper >; /** * @brief Create an update kernel wrapper. @@ -262,13 +259,13 @@ class MultiPhaseMultiComponentFluid : public MultiFluidBase */ KernelWrapper createKernelWrapper() { - return KernelWrapper( m_phaseGasIndex, - m_phaseLiquidIndex, - m_brineViscosityWrapper.toViewConst(), - m_co2ViscosityWrapper.toViewConst(), - m_brineDensityWrapper.toViewConst(), - m_co2DensityWrapper.toViewConst(), - m_co2SolubilityWrapper.toViewConst(), + return KernelWrapper( m_p1Index, + m_p2Index, + m_p1DensityWrapper.toViewConst(), + m_p1ViscosityWrapper.toViewConst(), + m_p2DensityWrapper.toViewConst(), + m_p2ViscosityWrapper.toViewConst(), + m_flashWrapper.toViewConst(), m_componentMolarWeight.toViewConst(), m_useMass, m_phaseFraction, @@ -303,7 +300,6 @@ class MultiPhaseMultiComponentFluid : public MultiFluidBase static constexpr char const * phasePVTParaFilesString() { return "phasePVTParaFiles"; } } viewKeysMultiPhaseMultiComponentFluid; - protected: virtual void postProcessInput() override; @@ -318,65 +314,87 @@ class MultiPhaseMultiComponentFluid : public MultiFluidBase /// Name of the file defining the flash model Path m_flashModelParaFile; - /// Index of the gas phase - localIndex m_phaseGasIndex; - /// Index of the liquid phase - localIndex m_phaseLiquidIndex; + localIndex m_p1Index; - // TODO: Here I hard-coded all the types to avoid the virtual calls in the compute function. - // See if there is a way to reintroduce them. If it is not possible, the class should be - // renamed because it is not "multi-phase, multi-component", but just CO2-brine. - - /// Pointer to the brine viscosity model - std::unique_ptr< PVTProps::BrineViscosity > m_brineViscosity; - - /// Pointer to the CO2 viscosity model - std::unique_ptr< PVTProps::FenghourCO2Viscosity > m_co2Viscosity; + /// Index of the gas phase + localIndex m_p2Index; /// Pointer to the brine density model - std::unique_ptr< PVTProps::BrineCO2Density > m_brineDensity; - - /// Pointer to the CO2 density model - std::unique_ptr< PVTProps::SpanWagnerCO2Density > m_co2Density; - - /// Pointer to the flash model - std::unique_ptr< PVTProps::CO2Solubility > m_co2Solubility; + std::unique_ptr< P1DENS > m_p1Density; /// Pointer to the brine viscosity model - array1d< PVTProps::BrineViscosity::KernelWrapper > m_brineViscosityWrapper; + std::unique_ptr< P1VISC > m_p1Viscosity; + + /// Pointer to the CO2 density model + std::unique_ptr< P2DENS > m_p2Density; /// Pointer to the CO2 viscosity model - array1d< PVTProps::FenghourCO2Viscosity::KernelWrapper > m_co2ViscosityWrapper; + std::unique_ptr< P2VISC > m_p2Viscosity; + + /// Pointer to the flash model + std::unique_ptr< FLASH > m_flash; /// Pointer to the brine density model - array1d< PVTProps::BrineCO2Density::KernelWrapper > m_brineDensityWrapper; + array1d< typename P1DENS::KernelWrapper > m_p1DensityWrapper; + + /// Pointer to the brine viscosity model + array1d< typename P1VISC::KernelWrapper > m_p1ViscosityWrapper; /// Pointer to the CO2 density model - array1d< PVTProps::SpanWagnerCO2Density::KernelWrapper > m_co2DensityWrapper; + array1d< typename P2DENS::KernelWrapper > m_p2DensityWrapper; + + /// Pointer to the CO2 viscosity model + array1d< typename P2VISC::KernelWrapper > m_p2ViscosityWrapper; /// Pointer to the flash model - array1d< PVTProps::CO2Solubility::KernelWrapper > m_co2SolubilityWrapper; + array1d< typename FLASH::KernelWrapper > m_flashWrapper; }; -template<> +// this alias will be useful in constitutive dispatch +using CO2BrineFluid = MultiPhaseMultiComponentFluid< PVTProps::BrineCO2Density, + PVTProps::BrineViscosity, + PVTProps::SpanWagnerCO2Density, + PVTProps::FenghourCO2Viscosity, + PVTProps::CO2Solubility >; + +// The constructor is in the hpp for one reason: the testMultiFluid won't link if the constructor is in the cpp +// I could not find a workaround +template< typename P1DENS, typename P1VISC, typename P2DENS, typename P2VISC, typename FLASH > +MultiPhaseMultiComponentFluid< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >:: +MultiPhaseMultiComponentFluid( string const & name, Group * const parent ): + MultiFluidBase( name, parent ) +{ + registerWrapper( viewKeyStruct::phasePVTParaFilesString(), &m_phasePVTParaFiles ). + setInputFlag( dataRepository::InputFlags::REQUIRED ). + setRestartFlags( dataRepository::RestartFlags::NO_WRITE ). + setDescription( "Names of the files defining the parameters of the viscosity and density models" ); + + registerWrapper( viewKeyStruct::flashModelParaFileString(), &m_flashModelParaFile ). + setInputFlag( dataRepository::InputFlags::REQUIRED ). + setRestartFlags( dataRepository::RestartFlags::NO_WRITE ). + setDescription( "Name of the file defining the parameters of the flash model" ); +} + +template< typename P1DENSWRAPPER, typename P1VISCWRAPPER, typename P2DENSWRAPPER, typename P2VISCWRAPPER, typename FLASHWRAPPER > GEOSX_HOST_DEVICE GEOSX_FORCE_INLINE -void MultiPhaseMultiComponentFluid::KernelWrapper::compute( real64 pressure, - real64 temperature, - arraySlice1d< real64 const > const & composition, - arraySlice1d< real64 > const & phaseFraction, - arraySlice1d< real64 > const & phaseDensity, - arraySlice1d< real64 > const & phaseMassDensity, - arraySlice1d< real64 > const & phaseViscosity, - arraySlice2d< real64 > const & phaseCompFraction, - real64 & totalDensity ) const +void MultiPhaseMultiComponentFluidUpdate< P1DENSWRAPPER, P1VISCWRAPPER, P2DENSWRAPPER, P2VISCWRAPPER, FLASHWRAPPER >:: +compute( real64 pressure, + real64 temperature, + arraySlice1d< real64 const > const & composition, + arraySlice1d< real64 > const & phaseFraction, + arraySlice1d< real64 > const & phaseDensity, + arraySlice1d< real64 > const & phaseMassDensity, + arraySlice1d< real64 > const & phaseViscosity, + arraySlice2d< real64 > const & phaseCompFraction, + real64 & totalDensity ) const { constexpr localIndex numComps = 2; constexpr localIndex numPhases = 2; - localIndex const ipGas = m_phaseGasIndex; - localIndex const ipLiq = m_phaseLiquidIndex; + localIndex const ip1 = m_p1Index; + localIndex const ip2 = m_p2Index; // for now, compute the derivatives and discard them stackArray1d< real64, numPhases > dPhaseFrac_dPres( numPhases ); @@ -425,35 +443,35 @@ void MultiPhaseMultiComponentFluid::KernelWrapper::compute( real64 pressure, // 2. Compute phase fractions and phase component fractions real64 const temperatureInCelsius = temperature - 273.15; - m_co2SolubilityWrapper[0].compute( pressure, - temperatureInCelsius, - compMoleFrac, - phaseFraction, dPhaseFrac_dPres, dPhaseFrac_dTemp, dPhaseFrac_dComp, - phaseCompFraction, dPhaseCompFrac_dPres, dPhaseCompFrac_dTemp, dPhaseCompFrac_dComp ); + m_flashWrapper[0].compute( pressure, + temperatureInCelsius, + compMoleFrac, + phaseFraction, dPhaseFrac_dPres, dPhaseFrac_dTemp, dPhaseFrac_dComp, + phaseCompFraction, dPhaseCompFrac_dPres, dPhaseCompFrac_dTemp, dPhaseCompFrac_dComp ); // 3. Compute phase densities and phase viscosities - m_co2DensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFraction[ipGas], - phaseDensity[ipGas], dPhaseDens_dPres, dPhaseDens_dTemp, dPhaseDens_dComp, - m_useMass ); - m_co2ViscosityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFraction[ipGas], - phaseViscosity[ipGas], dPhaseVisc_dPres, dPhaseVisc_dTemp, dPhaseVisc_dComp, - m_useMass ); - - m_brineDensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFraction[ipLiq], - phaseDensity[ipLiq], dPhaseDens_dPres, dPhaseDens_dTemp, dPhaseDens_dComp, - m_useMass ); - m_brineViscosityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFraction[ipLiq], - phaseViscosity[ipLiq], dPhaseVisc_dPres, dPhaseVisc_dTemp, dPhaseVisc_dComp, - m_useMass ); + m_p1DensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFraction[ip1], + phaseDensity[ip1], dPhaseDens_dPres, dPhaseDens_dTemp, dPhaseDens_dComp, + m_useMass ); + m_p1ViscosityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFraction[ip1], + phaseViscosity[ip1], dPhaseVisc_dPres, dPhaseVisc_dTemp, dPhaseVisc_dComp, + m_useMass ); + + m_p2DensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFraction[ip2], + phaseDensity[ip2], dPhaseDens_dPres, dPhaseDens_dTemp, dPhaseDens_dComp, + m_useMass ); + m_p2ViscosityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFraction[ip2], + phaseViscosity[ip2], dPhaseVisc_dPres, dPhaseVisc_dTemp, dPhaseVisc_dComp, + m_useMass ); // 4. Depending on the m_useMass flag, convert to mass variables or simply compute mass density @@ -472,18 +490,19 @@ void MultiPhaseMultiComponentFluid::KernelWrapper::compute( real64 pressure, real64 dPhaseMolarDens_dPres = 0.0; real64 dPhaseMolarDens_dTemp = 0.0; stackArray1d< real64, numComps > dPhaseMolarDens_dComp( 2 ); - m_co2DensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFraction[ipGas], - phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, - 0 ); - phaseMW[ipGas] = phaseDensity[ipGas] / phaseMolarDens; - m_brineDensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFraction[ipLiq], - phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, - 0 ); - phaseMW[ipLiq] = phaseDensity[ipLiq] / phaseMolarDens; + m_p1DensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFraction[ip1], + phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, + 0 ); + phaseMW[ip1] = phaseDensity[ip1] / phaseMolarDens; + + m_p2DensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFraction[ip2], + phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, + 0 ); + phaseMW[ip2] = phaseDensity[ip2] / phaseMolarDens; // 4.1.1. Compute mass of each phase and total mass (on a 1-mole basis) for( localIndex ip = 0; ip < numPhases; ++ip ) @@ -517,18 +536,18 @@ void MultiPhaseMultiComponentFluid::KernelWrapper::compute( real64 pressure, else { // for now, we have to compute the phase mass density here - m_co2DensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFraction[ipGas], - phaseMassDensity[ipGas], dPhaseMassDens_dPres, - dPhaseMassDens_dTemp, dPhaseMassDens_dComp, - true ); - m_brineDensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFraction[ipLiq], - phaseMassDensity[ipLiq], dPhaseMassDens_dPres, - dPhaseMassDens_dTemp, dPhaseMassDens_dComp, - true ); + m_p1DensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFraction[ip1], + phaseMassDensity[ip1], dPhaseMassDens_dPres, + dPhaseMassDens_dTemp, dPhaseMassDens_dComp, + true ); + m_p2DensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFraction[ip2], + phaseMassDensity[ip2], dPhaseMassDens_dPres, + dPhaseMassDens_dTemp, dPhaseMassDens_dComp, + true ); } // TODO: extract the following piece of code and write a function that can be used here and in MultiFluidPVTPackageWrapper @@ -548,36 +567,37 @@ void MultiPhaseMultiComponentFluid::KernelWrapper::compute( real64 pressure, } } -template<> +template< typename P1DENSWRAPPER, typename P1VISCWRAPPER, typename P2DENSWRAPPER, typename P2VISCWRAPPER, typename FLASHWRAPPER > GEOSX_HOST_DEVICE GEOSX_FORCE_INLINE -void MultiPhaseMultiComponentFluid::KernelWrapper::compute( real64 pressure, - real64 temperature, - arraySlice1d< real64 const > const & composition, - arraySlice1d< real64 > const & phaseFraction, - arraySlice1d< real64 > const & dPhaseFraction_dPressure, - arraySlice1d< real64 > const & dPhaseFraction_dTemperature, - arraySlice2d< real64 > const & dPhaseFraction_dGlobalCompFraction, - arraySlice1d< real64 > const & phaseDensity, - arraySlice1d< real64 > const & dPhaseDensity_dPressure, - arraySlice1d< real64 > const & dPhaseDensity_dTemperature, - arraySlice2d< real64 > const & dPhaseDensity_dGlobalCompFraction, - arraySlice1d< real64 > const & phaseMassDensity, - arraySlice1d< real64 > const & dPhaseMassDensity_dPressure, - arraySlice1d< real64 > const & dPhaseMassDensity_dTemperature, - arraySlice2d< real64 > const & dPhaseMassDensity_dGlobalCompFraction, - arraySlice1d< real64 > const & phaseViscosity, - arraySlice1d< real64 > const & dPhaseViscosity_dPressure, - arraySlice1d< real64 > const & dPhaseViscosity_dTemperature, - arraySlice2d< real64 > const & dPhaseViscosity_dGlobalCompFraction, - arraySlice2d< real64 > const & phaseCompFraction, - arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, - arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, - arraySlice3d< real64 > const & dPhaseCompFraction_dGlobalCompFraction, - real64 & totalDensity, - real64 & dTotalDensity_dPressure, - real64 & dTotalDensity_dTemperature, - arraySlice1d< real64 > const & dTotalDensity_dGlobalCompFraction ) const +void MultiPhaseMultiComponentFluidUpdate< P1DENSWRAPPER, P1VISCWRAPPER, P2DENSWRAPPER, P2VISCWRAPPER, FLASHWRAPPER >:: +compute( real64 pressure, + real64 temperature, + arraySlice1d< real64 const > const & composition, + arraySlice1d< real64 > const & phaseFraction, + arraySlice1d< real64 > const & dPhaseFraction_dPressure, + arraySlice1d< real64 > const & dPhaseFraction_dTemperature, + arraySlice2d< real64 > const & dPhaseFraction_dGlobalCompFraction, + arraySlice1d< real64 > const & phaseDensity, + arraySlice1d< real64 > const & dPhaseDensity_dPressure, + arraySlice1d< real64 > const & dPhaseDensity_dTemperature, + arraySlice2d< real64 > const & dPhaseDensity_dGlobalCompFraction, + arraySlice1d< real64 > const & phaseMassDensity, + arraySlice1d< real64 > const & dPhaseMassDensity_dPressure, + arraySlice1d< real64 > const & dPhaseMassDensity_dTemperature, + arraySlice2d< real64 > const & dPhaseMassDensity_dGlobalCompFraction, + arraySlice1d< real64 > const & phaseViscosity, + arraySlice1d< real64 > const & dPhaseViscosity_dPressure, + arraySlice1d< real64 > const & dPhaseViscosity_dTemperature, + arraySlice2d< real64 > const & dPhaseViscosity_dGlobalCompFraction, + arraySlice2d< real64 > const & phaseCompFraction, + arraySlice2d< real64 > const & dPhaseCompFraction_dPressure, + arraySlice2d< real64 > const & dPhaseCompFraction_dTemperature, + arraySlice3d< real64 > const & dPhaseCompFraction_dGlobalCompFraction, + real64 & totalDensity, + real64 & dTotalDensity_dPressure, + real64 & dTotalDensity_dTemperature, + arraySlice1d< real64 > const & dTotalDensity_dGlobalCompFraction ) const { // 0. make shortcut structs to avoid long names (TODO maybe remove) CompositionalVarContainer< 1 > phaseFrac { @@ -629,8 +649,8 @@ void MultiPhaseMultiComponentFluid::KernelWrapper::compute( real64 pressure, constexpr localIndex numComps = 2; constexpr localIndex numPhases = 2; - localIndex const ipGas = m_phaseGasIndex; - localIndex const ipLiq = m_phaseLiquidIndex; + localIndex const ip1 = m_p1Index; + localIndex const ip2 = m_p2Index; // 1. Convert input mass fractions to mole fractions and keep derivatives @@ -671,35 +691,34 @@ void MultiPhaseMultiComponentFluid::KernelWrapper::compute( real64 pressure, // 2. Compute phase fractions and phase component fractions real64 const temperatureInCelsius = temperature - 273.15; - m_co2SolubilityWrapper[0].compute( pressure, - temperatureInCelsius, - compMoleFrac, - phaseFrac.value, phaseFrac.dPres, phaseFrac.dTemp, phaseFrac.dComp, - phaseCompFrac.value, phaseCompFrac.dPres, phaseCompFrac.dTemp, phaseCompFrac.dComp ); + m_flashWrapper[0].compute( pressure, + temperatureInCelsius, + compMoleFrac, + phaseFrac.value, phaseFrac.dPres, phaseFrac.dTemp, phaseFrac.dComp, + phaseCompFrac.value, phaseCompFrac.dPres, phaseCompFrac.dTemp, phaseCompFrac.dComp ); // 3. Compute phase densities and phase viscosities - m_co2DensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFrac.value[ipGas], - phaseDens.value[ipGas], phaseDens.dPres[ipGas], phaseDens.dTemp[ipGas], phaseDens.dComp[ipGas], - m_useMass ); - m_co2ViscosityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFrac.value[ipGas], - phaseVisc.value[ipGas], phaseVisc.dPres[ipGas], phaseVisc.dTemp[ipGas], phaseVisc.dComp[ipGas], - m_useMass ); - - m_brineDensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFrac.value[ipLiq], - phaseDens.value[ipLiq], phaseDens.dPres[ipLiq], phaseDens.dTemp[ipLiq], phaseDens.dComp[ipLiq], - m_useMass ); - m_brineViscosityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFrac.value[ipLiq], - phaseVisc.value[ipLiq], phaseVisc.dPres[ipLiq], phaseVisc.dTemp[ipLiq], phaseVisc.dComp[ipLiq], - m_useMass ); + m_p1DensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ip1], + phaseDens.value[ip1], phaseDens.dPres[ip1], phaseDens.dTemp[ip1], phaseDens.dComp[ip1], + m_useMass ); + m_p1ViscosityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ip1], + phaseVisc.value[ip1], phaseVisc.dPres[ip1], phaseVisc.dTemp[ip1], phaseVisc.dComp[ip1], + m_useMass ); + m_p2DensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ip2], + phaseDens.value[ip2], phaseDens.dPres[ip2], phaseDens.dTemp[ip2], phaseDens.dComp[ip2], + m_useMass ); + m_p2ViscosityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ip2], + phaseVisc.value[ip2], phaseVisc.dPres[ip2], phaseVisc.dTemp[ip2], phaseVisc.dComp[ip2], + m_useMass ); // 4. Depending on the m_useMass flag, convert to mass variables or simply compute mass density @@ -724,29 +743,29 @@ void MultiPhaseMultiComponentFluid::KernelWrapper::compute( real64 pressure, real64 dPhaseMolarDens_dPres = 0.0; real64 dPhaseMolarDens_dTemp = 0.0; stackArray1d< real64, numComps > dPhaseMolarDens_dComp( 2 ); - m_co2DensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFrac.value[ipGas], - phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, - 0 ); - phaseMW[ipGas] = phaseDens.value[ipGas] / phaseMolarDens; - dPhaseMW_dPres[ipGas] = phaseDens.dPres[ipGas] / phaseMolarDens - phaseMW[ipGas]*dPhaseMolarDens_dPres / phaseMolarDens; - dPhaseMW_dTemp[ipGas] = phaseDens.dTemp[ipGas] / phaseMolarDens - phaseMW[ipGas]*dPhaseMolarDens_dTemp / phaseMolarDens; + m_p2DensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ip2], + phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, + 0 ); + phaseMW[ip2] = phaseDens.value[ip2] / phaseMolarDens; + dPhaseMW_dPres[ip2] = phaseDens.dPres[ip2] / phaseMolarDens - phaseMW[ip2]*dPhaseMolarDens_dPres / phaseMolarDens; + dPhaseMW_dTemp[ip2] = phaseDens.dTemp[ip2] / phaseMolarDens - phaseMW[ip2]*dPhaseMolarDens_dTemp / phaseMolarDens; for( localIndex ic = 0; ic < numComps; ++ic ) { - dPhaseMW_dComp[ipGas][ic] = phaseDens.dComp[ipGas][ic] / phaseMolarDens - phaseMW[ipGas]*dPhaseMolarDens_dComp[ic] / phaseMolarDens; + dPhaseMW_dComp[ip2][ic] = phaseDens.dComp[ip2][ic] / phaseMolarDens - phaseMW[ip2]*dPhaseMolarDens_dComp[ic] / phaseMolarDens; } - m_brineDensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFrac.value[ipLiq], - phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, - 0 ); - phaseMW[ipLiq] = phaseDens.value[ipLiq] / phaseMolarDens; - dPhaseMW_dPres[ipLiq] = phaseDens.dPres[ipLiq] / phaseMolarDens - phaseMW[ipLiq]*dPhaseMolarDens_dPres / phaseMolarDens; - dPhaseMW_dTemp[ipLiq] = phaseDens.dTemp[ipLiq] / phaseMolarDens - phaseMW[ipLiq]*dPhaseMolarDens_dTemp / phaseMolarDens; + m_p1DensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ip1], + phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, + 0 ); + phaseMW[ip1] = phaseDens.value[ip1] / phaseMolarDens; + dPhaseMW_dPres[ip1] = phaseDens.dPres[ip1] / phaseMolarDens - phaseMW[ip1]*dPhaseMolarDens_dPres / phaseMolarDens; + dPhaseMW_dTemp[ip1] = phaseDens.dTemp[ip1] / phaseMolarDens - phaseMW[ip1]*dPhaseMolarDens_dTemp / phaseMolarDens; for( localIndex ic = 0; ic < numComps; ++ic ) { - dPhaseMW_dComp[ipLiq][ic] = phaseDens.dComp[ipLiq][ic] / phaseMolarDens - phaseMW[ipLiq]*dPhaseMolarDens_dComp[ic]/phaseMolarDens; + dPhaseMW_dComp[ip1][ic] = phaseDens.dComp[ip1][ic] / phaseMolarDens - phaseMW[ip1]*dPhaseMolarDens_dComp[ic]/phaseMolarDens; } @@ -836,18 +855,18 @@ void MultiPhaseMultiComponentFluid::KernelWrapper::compute( real64 pressure, else { // for now, we have to compute the phase mass density here - m_co2DensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFrac.value[ipGas], - phaseMassDens.value[ipGas], phaseMassDens.dPres[ipGas], - phaseMassDens.dTemp[ipGas], phaseMassDens.dComp[ipGas], - true ); - m_brineDensityWrapper[0].compute( pressure, - temperatureInCelsius, - phaseCompFrac.value[ipLiq], - phaseMassDens.value[ipLiq], phaseMassDens.dPres[ipLiq], - phaseMassDens.dTemp[ipLiq], phaseMassDens.dComp[ipLiq], - true ); + m_p1DensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ip1], + phaseMassDens.value[ip1], phaseMassDens.dPres[ip1], + phaseMassDens.dTemp[ip1], phaseMassDens.dComp[ip1], + true ); + m_p2DensityWrapper[0].compute( pressure, + temperatureInCelsius, + phaseCompFrac.value[ip2], + phaseMassDens.value[ip2], phaseMassDens.dPres[ip2], + phaseMassDens.dTemp[ip2], phaseMassDens.dComp[ip2], + true ); } // TODO: extract the following piece of code and write a function that can be used here and in MultiFluidPVTPackageWrapper diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp index 4d4dcac0317..97dc30efec9 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp @@ -41,11 +41,15 @@ BrineCO2Density::BrineCO2Density( string_array const & inputPara, { char const * expectedCO2ComponentNames[] = { "CO2", "co2" }; m_CO2Index = PVTFunctionHelpers::findName( componentNames, expectedCO2ComponentNames ); - GEOSX_ERROR_IF( m_CO2Index < 0 || m_CO2Index >= componentNames.size(), "Component CO2 is not found!" ); + GEOSX_THROW_IF( m_CO2Index < 0 || m_CO2Index >= componentNames.size(), + "Component CO2 is not found!", + InputError ); char const * expectedWaterComponentNames[] = { "Water", "water" }; m_waterIndex = PVTFunctionHelpers::findName( componentNames, expectedWaterComponentNames ); - GEOSX_ERROR_IF( m_waterIndex < 0 || m_waterIndex >= componentNames.size(), "Component Water/Brine is not found!" ); + GEOSX_THROW_IF( m_waterIndex < 0 || m_waterIndex >= componentNames.size(), + "Component Water/Brine is not found!", + InputError ); makeTable( inputPara ); } @@ -84,17 +88,20 @@ void BrineCO2Density::calculateBrineDensity( PTTableCoordinates const & tableCoo constexpr real64 CC = -8.750567; constexpr real64 DD = 2.663107; - for( localIndex i = 0; i < tableCoords.nPressures(); ++i ) + localIndex const nPressures = tableCoords.nPressures(); + localIndex const nTemperatures = tableCoords.nTemperatures(); + + for( localIndex i = 0; i < nPressures; ++i ) { real64 const P = tableCoords.getPressure( i ) / 1e5; - for( localIndex j = 0; j < tableCoords.nTemperatures(); ++j ) + for( localIndex j = 0; j < nTemperatures; ++j ) { // see Phillips et al. (1981), equations (4) and (5), pages 14 and 15 real64 const x = c1 * exp( a1 * salinity ) + c2 * exp( a2 * tableCoords.getTemperature( j ) ) + c3 * exp( a3 * P ); - densities[j*tableCoords.nPressures()+i] = (AA + BB * x + CC * x * x + DD * x * x * x) * 1000.0; + densities[j*nPressures+i] = (AA + BB * x + CC * x * x + DD * x * x * x) * 1000.0; } } } diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp index 5667cea57e2..32f711f475c 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp @@ -136,28 +136,38 @@ CO2Solubility::CO2Solubility( string_array const & inputPara, componentNames, componentMolarWeight ) { - GEOSX_ERROR_IF( phaseNames.size() != 2, "The CO2Solubility model is a two-phase model" ); - GEOSX_ERROR_IF( componentNames.size() != 2, "The CO2Solubility model is a two-component model" ); + GEOSX_THROW_IF( phaseNames.size() != 2, + "The CO2Solubility model is a two-phase model", + InputError ); + GEOSX_THROW_IF( componentNames.size() != 2, + "The CO2Solubility model is a two-component model", + InputError ); char const * expectedCO2ComponentNames[] = { "CO2", "co2" }; m_CO2Index = PVTFunctionHelpers::findName( componentNames, expectedCO2ComponentNames ); - GEOSX_ERROR_IF( m_CO2Index < 0 || m_CO2Index >= componentNames.size(), "Component CO2 is not found!" ); + GEOSX_THROW_IF( m_CO2Index < 0 || m_CO2Index >= componentNames.size(), + "Component CO2 is not found!", + InputError ); char const * expectedWaterComponentNames[] = { "Water", "water" }; m_waterIndex = PVTFunctionHelpers::findName( componentNames, expectedWaterComponentNames ); - GEOSX_ERROR_IF( m_waterIndex < 0 || m_waterIndex >= componentNames.size(), "Component Water/Brine is not found!" ); + GEOSX_THROW_IF( m_waterIndex < 0 || m_waterIndex >= componentNames.size(), + "Component Water/Brine is not found!", + InputError ); char const * expectedGasPhaseNames[] = { "CO2", "co2", "gas", "Gas" }; m_phaseGasIndex = PVTFunctionHelpers::findName( phaseNames, expectedGasPhaseNames ); - GEOSX_ERROR_IF( m_phaseGasIndex < 0 || m_phaseGasIndex >= phaseNames.size(), - "Phase co2/gas is not found!" ); + GEOSX_THROW_IF( m_phaseGasIndex < 0 || m_phaseGasIndex >= phaseNames.size(), + "Phase co2/gas is not found!", + InputError ); char const * expectedWaterPhaseNames[] = { "Water", "water", "Liquid", "liquid" }; m_phaseLiquidIndex = PVTFunctionHelpers::findName( phaseNames, expectedWaterPhaseNames ); - GEOSX_ERROR_IF( m_phaseLiquidIndex < 0 || m_phaseLiquidIndex >= phaseNames.size(), - "Phase water/liquid is not found!" ); + GEOSX_THROW_IF( m_phaseLiquidIndex < 0 || m_phaseLiquidIndex >= phaseNames.size(), + "Phase water/liquid is not found!", + InputError ); makeTable( inputPara ); } @@ -189,11 +199,14 @@ void CO2Solubility::calculateCO2Solubility( PTTableCoordinates const & tableCoor constexpr real64 lambda[] = { -0.411370585, 6.07632013e-4, 97.5347708, 0, 0, 0, 0, -0.0237622469, 0.0170656236, 0, 1.41335834e-5 }; constexpr real64 zeta[] = { 3.36389723e-4, -1.98298980e-5, 0, 0, 0, 0, 0, 2.12220830e-3, -5.24873303e-3, 0, 0 }; - for( localIndex i = 0; i < tableCoords.nPressures(); ++i ) + localIndex const nPressures = tableCoords.nPressures(); + localIndex const nTemperatures = tableCoords.nTemperatures(); + + for( localIndex i = 0; i < nPressures; ++i ) { real64 const P = tableCoords.getPressure( i ) / P_Pa_f; - for( localIndex j = 0; j < tableCoords.nTemperatures(); ++j ) + for( localIndex j = 0; j < nTemperatures; ++j ) { real64 const T = tableCoords.getTemperature( j ); @@ -245,7 +258,9 @@ void CO2Solubility::CO2SolubilityFunction( real64 const & T, break; } - GEOSX_ERROR_IF( count > 50, "CO2Solubility NR convergence fails! " << "dre = " << dre << ", eps = " << eps ); + GEOSX_THROW_IF( count > 50, + "CO2Solubility NR convergence fails! " << "dre = " << dre << ", eps = " << eps, + InputError ); count++; V_r += dre; diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp index 4119c335f47..d6e27f684f7 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp @@ -43,8 +43,9 @@ FenghourCO2Viscosity::FenghourCO2Viscosity( string_array const & inputPara, void FenghourCO2Viscosity::makeTable( string_array const & inputPara ) { + localIndex const expectedNumParameters = 8; PTTableCoordinates tableCoords; - PVTFunctionHelpers::initializePropertyTable( inputPara, tableCoords ); + PVTFunctionHelpers::initializePropertyTable( inputPara, expectedNumParameters, tableCoords ); localIndex const nP = tableCoords.nPressures(); localIndex const nT = tableCoords.nTemperatures(); @@ -101,13 +102,17 @@ void FenghourCO2Viscosity::calculateCO2Viscosity( PTTableCoordinates const & tab array1d< real64 > const & densities, array1d< real64 > const & viscosities ) { - for( localIndex i = 0; i < tableCoords.nPressures(); ++i ) + + localIndex const nPressures = tableCoords.nPressures(); + localIndex const nTemperatures = tableCoords.nTemperatures(); + + for( localIndex i = 0; i < nPressures; ++i ) { - for( localIndex j = 0; j < tableCoords.nTemperatures(); ++j ) + for( localIndex j = 0; j < nTemperatures; ++j ) { fenghourCO2ViscosityFunction( tableCoords.getTemperature( j ), - densities[j*tableCoords.nPressures()+i], - viscosities[j*tableCoords.nPressures()+i] ); + densities[j*nPressures+i], + viscosities[j*nPressures+i] ); } } } diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/FlashModelBase.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/FlashModelBase.hpp index 4e3df8dedf1..9be4ae19518 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/FlashModelBase.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/FlashModelBase.hpp @@ -86,7 +86,7 @@ class FlashModelBase public: FlashModelBase( string const & name, - array1d< string > const & componentNames, + string_array const & componentNames, array1d< real64 > const & componentMolarWeight ): m_modelName( name ), m_componentNames( componentNames ), @@ -95,9 +95,9 @@ class FlashModelBase virtual ~FlashModelBase() = default; - using CatalogInterface = dataRepository::CatalogInterface< FlashModelBase, array1d< string > const &, - array1d< string > const &, - array1d< string > const &, + using CatalogInterface = dataRepository::CatalogInterface< FlashModelBase, string_array const &, + string_array const &, + string_array const &, array1d< real64 > const & >; static typename CatalogInterface::CatalogType & getCatalog() { @@ -115,7 +115,7 @@ class FlashModelBase string m_modelName; /// Array storing the name of the components - array1d< string > m_componentNames; + string_array m_componentNames; /// Array storing the component molar weights array1d< real64 > m_componentMolarWeight; diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp index d1522aebd43..a2d3593c48a 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp @@ -34,18 +34,25 @@ class PTTableCoordinates PTTableCoordinates() { coords.resize( 2 ); } - localIndex nPressures() const { return coords[0].size(); } - localIndex nTemperatures() const { return coords[1].size(); } + localIndex nPressures() const { return coords[coordType::PRES].size(); } + localIndex nTemperatures() const { return coords[coordType::TEMP].size(); } - void appendPressure( const real64 & pres ) { coords[0].emplace_back( pres ); } - void appendTemperature( const real64 & temp ) { coords[1].emplace_back( temp ); } + void appendPressure( const real64 & pres ) { coords[coordType::PRES].emplace_back( pres ); } + void appendTemperature( const real64 & temp ) { coords[coordType::TEMP].emplace_back( temp ); } - real64 const & getPressure( localIndex i ) const { return coords[0][i]; } - real64 const & getTemperature( localIndex i ) const { return coords[1][i]; } + real64 const & getPressure( localIndex i ) const { return coords[coordType::PRES][i]; } + real64 const & getTemperature( localIndex i ) const { return coords[coordType::TEMP][i]; } array1d< array1d< real64 > > const & getCoords() const { return coords; } private: + + struct coordType + { + static constexpr integer PRES = 0; + static constexpr integer TEMP = 1; + }; + array1d< array1d< real64 > > coords; }; @@ -70,60 +77,47 @@ struct PVTFunctionHelpers return id; } + /** + * @brief Populate the coordinate table with pressure and temperature + * @param[in] inputParameters the strings reads in the file provided by the user + * @param[inout] tableCoords the (p,T) coordinates of the table + */ static real64 initializePropertyTableWithSalinity( string_array const & inputParameters, PTTableCoordinates & tableCoords ) { - real64 TStart = -1.0; - real64 TEnd = -1.0; - real64 dT = -1.0; - real64 PStart = -1.0; - real64 PEnd = -1.0; - real64 dP = -1.0; - real64 salinity = -1.0; - - GEOSX_ERROR_IF( inputParameters.size() != 9, "Invalid property input!" ); - + localIndex const expectedNumParameters = 9; + real64 salinity = 0.0; + initializePropertyTable( inputParameters, expectedNumParameters, tableCoords ); try { - PStart = stod( inputParameters[2] ); - PEnd = stod( inputParameters[3] ); - dP = stod( inputParameters[4] ); - - TStart = stod( inputParameters[5] ); - TEnd = stod( inputParameters[6] ); - dT = stod( inputParameters[7] ); - salinity = stod( inputParameters[8] ); } catch( const std::invalid_argument & e ) { - GEOSX_ERROR( "Invalid BrineCO2Density argument:" + string( e.what()) ); - } - - for( real64 P = PStart; P <= PEnd; P += dP ) - { - tableCoords.appendPressure( P ); - } - for( real64 T = TStart; T <= TEnd; T += dT ) - { - tableCoords.appendTemperature( T ); + GEOSX_THROW( "Invalid property argument:" + string( e.what()), + InputError ); } return salinity; } + /** + * @brief Populate the coordinate table with pressure and temperature + * @param[in] inputParameters the strings reads in the file provided by the user + * @param[in] expectedNumParameters the number of expected parameters in the file provided by the user + * @param[inout] tableCoords the (p,T) coordinates of the table + */ static void initializePropertyTable( string_array const & inputParameters, + localIndex const expectedNumParameters, PTTableCoordinates & tableCoords ) + { - real64 TStart = -1.0; - real64 TEnd = -1.0; - real64 dT = -1.0; - real64 PStart = -1.0; - real64 PEnd = -1.0; - real64 dP = -1.0; + real64 TStart, TEnd, dT, PStart, PEnd, dP; - GEOSX_ERROR_IF( inputParameters.size() != 8, "Invalid property input!" ); + GEOSX_THROW_IF( inputParameters.size() != expectedNumParameters, + "Invalid property input!", + InputError ); try { @@ -134,19 +128,20 @@ struct PVTFunctionHelpers TStart = stod( inputParameters[5] ); TEnd = stod( inputParameters[6] ); dT = stod( inputParameters[7] ); - } - catch( const std::invalid_argument & e ) - { - GEOSX_ERROR( "Invalid property argument:" + string( e.what()) ); - } - for( real64 P = PStart; P <= PEnd; P += dP ) - { - tableCoords.appendPressure( P ); + for( real64 P = PStart; P <= PEnd; P += dP ) + { + tableCoords.appendPressure( P ); + } + for( real64 T = TStart; T <= TEnd; T += dT ) + { + tableCoords.appendTemperature( T ); + } } - for( real64 T = TStart; T <= TEnd; T += dT ) + catch( const std::invalid_argument & e ) { - tableCoords.appendTemperature( T ); + GEOSX_THROW( "Invalid property argument:" + string( e.what()), + InputError ); } } diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp index 64f06866d57..a29bd62fdff 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp @@ -148,15 +148,18 @@ SpanWagnerCO2Density::SpanWagnerCO2Density( string_array const & inputPara, { char const * expectedCO2ComponentNames[] = { "CO2", "co2" }; m_CO2Index = PVTFunctionHelpers::findName( componentNames, expectedCO2ComponentNames ); - GEOSX_ERROR_IF( m_CO2Index < 0 || m_CO2Index >= componentNames.size(), "Component CO2 is not found!" ); + GEOSX_THROW_IF( m_CO2Index < 0 || m_CO2Index >= componentNames.size(), + "Component CO2 is not found!", + InputError ); makeTable( inputPara ); } void SpanWagnerCO2Density::makeTable( string_array const & inputPara ) { + localIndex const expectedNumParameters = 8; PTTableCoordinates tableCoords; - PVTFunctionHelpers::initializePropertyTable( inputPara, tableCoords ); + PVTFunctionHelpers::initializePropertyTable( inputPara, expectedNumParameters, tableCoords ); array1d< real64 > densities( tableCoords.nPressures() * tableCoords.nTemperatures() ); calculateCO2Density( tableCoords, densities ); @@ -176,13 +179,16 @@ void SpanWagnerCO2Density::calculateCO2Density( PTTableCoordinates const & table constexpr real64 TK_f = 273.15; - for( localIndex i = 0; i < tableCoords.nPressures(); ++i ) + localIndex const nPressures = tableCoords.nPressures(); + localIndex const nTemperatures = tableCoords.nTemperatures(); + + for( localIndex i = 0; i < nPressures; ++i ) { real64 const PPa = tableCoords.getPressure( i ); - for( localIndex j = 0; j < tableCoords.nTemperatures(); ++j ) + for( localIndex j = 0; j < nTemperatures; ++j ) { real64 const TK = tableCoords.getTemperature( j ) + TK_f; - spanWagnerCO2DensityFunction( TK, PPa, densities[j*tableCoords.nPressures()+i], &detail::f ); + spanWagnerCO2DensityFunction( TK, PPa, densities[j*nPressures+i], &detail::f ); } } } diff --git a/src/coreComponents/constitutive/fluid/multiFluidSelector.hpp b/src/coreComponents/constitutive/fluid/multiFluidSelector.hpp index b96302b2571..ea8c625ba7c 100644 --- a/src/coreComponents/constitutive/fluid/multiFluidSelector.hpp +++ b/src/coreComponents/constitutive/fluid/multiFluidSelector.hpp @@ -37,7 +37,7 @@ void constitutiveUpdatePassThru( MultiFluidBase const & fluid, ConstitutivePassThruHandler< DeadOilFluid, BlackOilFluid, CompositionalMultiphaseFluid, - MultiPhaseMultiComponentFluid >::execute( fluid, std::forward< LAMBDA >( lambda ) ); + CO2BrineFluid >::execute( fluid, std::forward< LAMBDA >( lambda ) ); } template< typename LAMBDA > @@ -47,7 +47,7 @@ void constitutiveUpdatePassThru( MultiFluidBase & fluid, ConstitutivePassThruHandler< DeadOilFluid, BlackOilFluid, CompositionalMultiphaseFluid, - MultiPhaseMultiComponentFluid >::execute( fluid, std::forward< LAMBDA >( lambda ) ); + CO2BrineFluid >::execute( fluid, std::forward< LAMBDA >( lambda ) ); } } // namespace constitutive diff --git a/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp b/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp index dc1b7e43b47..e8ba1169ec6 100644 --- a/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp +++ b/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp @@ -22,7 +22,6 @@ #include "managers/Functions/FunctionManager.hpp" #include "managers/GeosxState.hpp" - // TPL includes #include #include @@ -281,7 +280,7 @@ void testNumericalDerivatives( MultiFluidBase & fluid, } ); } -void testValuesAgainstPreviousImplementation( MultiPhaseMultiComponentFluid::KernelWrapper const & wrapper, +void testValuesAgainstPreviousImplementation( CO2BrineFluid::KernelWrapper const & wrapper, real64 const P, real64 const T, arraySlice1d< real64 > const & composition, @@ -802,9 +801,15 @@ TEST_F( DeadOilFluidFromTableTest, numericalDerivativesMolar ) } } +template class MultiPhaseMultiComponentFluid< PVTProps::BrineCO2Density, + PVTProps::BrineViscosity, + PVTProps::SpanWagnerCO2Density, + PVTProps::FenghourCO2Viscosity, + PVTProps::CO2Solubility >; + MultiFluidBase & makeMultiPhaseMultiComponentFluid( string const & name, Group * parent ) { - MultiPhaseMultiComponentFluid & fluid = parent->registerGroup< MultiPhaseMultiComponentFluid >( name ); + CO2BrineFluid & fluid = parent->registerGroup< CO2BrineFluid >( name ); auto & compNames = fluid.getReference< string_array >( MultiFluidBase::viewKeyStruct::componentNamesString() ); compNames.resize( 2 ); @@ -818,11 +823,11 @@ MultiFluidBase & makeMultiPhaseMultiComponentFluid( string const & name, Group * phaseNames.resize( 2 ); phaseNames[0] = "gas"; phaseNames[1] = "liquid"; - auto & phasePVTParaFileNames = fluid.getReference< path_array >( MultiPhaseMultiComponentFluid::viewKeyStruct::phasePVTParaFilesString() ); + auto & phasePVTParaFileNames = fluid.getReference< path_array >( CO2BrineFluid::viewKeyStruct::phasePVTParaFilesString() ); phasePVTParaFileNames.resize( 2 ); phasePVTParaFileNames[0] = "pvtgas.txt"; phasePVTParaFileNames[1] = "pvtliquid.txt"; - auto & flashModelParaFileName = fluid.getReference< Path >( MultiPhaseMultiComponentFluid::viewKeyStruct::flashModelParaFileString() ); + auto & flashModelParaFileName = fluid.getReference< Path >( CO2BrineFluid::viewKeyStruct::flashModelParaFileString() ); flashModelParaFileName = "co2flash.txt"; fluid.postProcessInputRecursive(); @@ -855,7 +860,7 @@ class MultiPhaseMultiComponentFluidTest : public CompositionalFluidTestBase }; -// TEMPORARY CODE TO VALIDATE NEW IMPLEMENTATION + TEST_F( MultiPhaseMultiComponentFluidTest, checkAgainstPreviousImplementationMolar ) { fluid->setMassFlag( false ); @@ -869,8 +874,8 @@ TEST_F( MultiPhaseMultiComponentFluidTest, checkAgainstPreviousImplementationMol fluid->allocateConstitutiveData( fluid->getParent(), 1 ); - MultiPhaseMultiComponentFluid::KernelWrapper wrapper = - dynamicCast< MultiPhaseMultiComponentFluid * >( fluid )->createKernelWrapper(); + CO2BrineFluid::KernelWrapper wrapper = + dynamicCast< CO2BrineFluid * >( fluid )->createKernelWrapper(); real64 const savedTotalDens[] = { 5881.8128183956969224, 5869.522096458530541, 5854.9469601674582009, 9180.9455320478591602, 9157.2045503913905122, 9129.1751063784995495, 15755.475565136142905, 15696.691553847707837, @@ -934,8 +939,8 @@ TEST_F( MultiPhaseMultiComponentFluidTest, checkAgainstPreviousImplementationMas fluid->allocateConstitutiveData( fluid->getParent(), 1 ); - MultiPhaseMultiComponentFluid::KernelWrapper wrapper = - dynamicCast< MultiPhaseMultiComponentFluid * >( fluid )->createKernelWrapper(); + CO2BrineFluid::KernelWrapper wrapper = + dynamicCast< CO2BrineFluid * >( fluid )->createKernelWrapper(); real64 const savedTotalDens[] = { 238.33977561940088208, 237.86350488026934613, 237.29874890241927687, 354.01144731214282046, 353.18618684355078585, 352.21120673560858449, 550.02182875764299297, 548.3889751707506548, diff --git a/src/coreComponents/fileIO/schema/docs/MultiPhaseMultiComponentFluid.rst b/src/coreComponents/fileIO/schema/docs/CO2BrineFluid.rst similarity index 100% rename from src/coreComponents/fileIO/schema/docs/MultiPhaseMultiComponentFluid.rst rename to src/coreComponents/fileIO/schema/docs/CO2BrineFluid.rst diff --git a/src/coreComponents/fileIO/schema/docs/MultiPhaseMultiComponentFluid_other.rst b/src/coreComponents/fileIO/schema/docs/CO2BrineFluid_other.rst similarity index 100% rename from src/coreComponents/fileIO/schema/docs/MultiPhaseMultiComponentFluid_other.rst rename to src/coreComponents/fileIO/schema/docs/CO2BrineFluid_other.rst diff --git a/src/coreComponents/fileIO/schema/docs/Constitutive.rst b/src/coreComponents/fileIO/schema/docs/Constitutive.rst index d2c6312e746..a00eea75555 100644 --- a/src/coreComponents/fileIO/schema/docs/Constitutive.rst +++ b/src/coreComponents/fileIO/schema/docs/Constitutive.rst @@ -7,6 +7,7 @@ BlackOilFluid node :ref:`XML_BlackOilFluid` BrooksCoreyBakerRelativePermeability node :ref:`XML_BrooksCoreyBakerRelativePermeability` BrooksCoreyCapillaryPressure node :ref:`XML_BrooksCoreyCapillaryPressure` BrooksCoreyRelativePermeability node :ref:`XML_BrooksCoreyRelativePermeability` +CO2BrineFluid node :ref:`XML_CO2BrineFluid` CompositionalMultiphaseFluid node :ref:`XML_CompositionalMultiphaseFluid` CompressibleSinglePhaseFluid node :ref:`XML_CompressibleSinglePhaseFluid` Contact node :ref:`XML_Contact` @@ -19,7 +20,6 @@ DruckerPrager node :ref:`XML_DruckerPrager` ElasticIsotropic node :ref:`XML_ElasticIsotropic` ElasticTransverseIsotropic node :ref:`XML_ElasticTransverseIsotropic` ExtendedDruckerPrager node :ref:`XML_ExtendedDruckerPrager` -MultiPhaseMultiComponentFluid node :ref:`XML_MultiPhaseMultiComponentFluid` NullModel node :ref:`XML_NullModel` ParticleFluid node :ref:`XML_ParticleFluid` PoreVolumeCompressibleSolid node :ref:`XML_PoreVolumeCompressibleSolid` diff --git a/src/coreComponents/fileIO/schema/docs/Constitutive_other.rst b/src/coreComponents/fileIO/schema/docs/Constitutive_other.rst index 9bc5975aa00..645b1a9a415 100644 --- a/src/coreComponents/fileIO/schema/docs/Constitutive_other.rst +++ b/src/coreComponents/fileIO/schema/docs/Constitutive_other.rst @@ -7,6 +7,7 @@ BlackOilFluid node :ref:`DATASTRUCTURE_BlackOilFluid` BrooksCoreyBakerRelativePermeability node :ref:`DATASTRUCTURE_BrooksCoreyBakerRelativePermeability` BrooksCoreyCapillaryPressure node :ref:`DATASTRUCTURE_BrooksCoreyCapillaryPressure` BrooksCoreyRelativePermeability node :ref:`DATASTRUCTURE_BrooksCoreyRelativePermeability` +CO2BrineFluid node :ref:`DATASTRUCTURE_CO2BrineFluid` CompositionalMultiphaseFluid node :ref:`DATASTRUCTURE_CompositionalMultiphaseFluid` CompressibleSinglePhaseFluid node :ref:`DATASTRUCTURE_CompressibleSinglePhaseFluid` Contact node :ref:`DATASTRUCTURE_Contact` @@ -19,7 +20,6 @@ DruckerPrager node :ref:`DATASTRUCTURE_DruckerPrager` ElasticIsotropic node :ref:`DATASTRUCTURE_ElasticIsotropic` ElasticTransverseIsotropic node :ref:`DATASTRUCTURE_ElasticTransverseIsotropic` ExtendedDruckerPrager node :ref:`DATASTRUCTURE_ExtendedDruckerPrager` -MultiPhaseMultiComponentFluid node :ref:`DATASTRUCTURE_MultiPhaseMultiComponentFluid` NullModel node :ref:`DATASTRUCTURE_NullModel` ParticleFluid node :ref:`DATASTRUCTURE_ParticleFluid` PoreVolumeCompressibleSolid node :ref:`DATASTRUCTURE_PoreVolumeCompressibleSolid` diff --git a/src/coreComponents/fileIO/schema/schema.xsd b/src/coreComponents/fileIO/schema/schema.xsd index 208f776c8c7..61f39b311d3 100644 --- a/src/coreComponents/fileIO/schema/schema.xsd +++ b/src/coreComponents/fileIO/schema/schema.xsd @@ -1625,6 +1625,7 @@ Equal to 1 for surface conditions, and to 0 for reservoir conditions--> + @@ -1637,7 +1638,6 @@ Equal to 1 for surface conditions, and to 0 for reservoir conditions--> - @@ -1711,6 +1711,20 @@ The expected format is "{ waterMax, oilMax }", in that order--> + + + + + + + + + + + + + + @@ -1960,20 +1974,6 @@ For instance, if "oil" is before "gas" in "phaseNames", the table order should b - - - - - - - - - - - - - - diff --git a/src/coreComponents/fileIO/schema/schema.xsd.other b/src/coreComponents/fileIO/schema/schema.xsd.other index a8e64a577ee..336e50c6e3e 100644 --- a/src/coreComponents/fileIO/schema/schema.xsd.other +++ b/src/coreComponents/fileIO/schema/schema.xsd.other @@ -688,6 +688,7 @@ + @@ -700,7 +701,6 @@ - @@ -802,6 +802,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1052,58 +1104,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/coreComponents/physicsSolvers/fluidFlow/integratedTests/compositionalMultiphaseFlow/co2_flux_3d.xml b/src/coreComponents/physicsSolvers/fluidFlow/integratedTests/compositionalMultiphaseFlow/co2_flux_3d.xml index f22bea933c7..dbc0ac73235 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/integratedTests/compositionalMultiphaseFlow/co2_flux_3d.xml +++ b/src/coreComponents/physicsSolvers/fluidFlow/integratedTests/compositionalMultiphaseFlow/co2_flux_3d.xml @@ -98,7 +98,7 @@ - - - - - Date: Thu, 11 Mar 2021 19:31:05 -0800 Subject: [PATCH 08/10] with constructor in cpp --- .../fluid/MultiPhaseMultiComponentFluid.cpp | 49 +++++++++---------- .../fluid/MultiPhaseMultiComponentFluid.hpp | 18 ------- 2 files changed, 22 insertions(+), 45 deletions(-) diff --git a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp index 0150dca803c..487c2481c72 100644 --- a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp +++ b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp @@ -57,33 +57,21 @@ string MultiPhaseMultiComponentFluid< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >::c return TwoPhaseCatalogNames< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >::name(); } -// explicit instantiation of the model template; unfortunately we can't use CO2BrineFluid alias for this -template class MultiPhaseMultiComponentFluid< PVTProps::BrineCO2Density, - PVTProps::BrineViscosity, - PVTProps::SpanWagnerCO2Density, - PVTProps::FenghourCO2Viscosity, - PVTProps::CO2Solubility >; - -// template< typename P1DENS, typename P1VISC, typename P2DENS, typename P2VISC, typename FLASH > -// MultiPhaseMultiComponentFluid< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >:: -// MultiPhaseMultiComponentFluid( string const & name, Group * const parent ): -// MultiFluidBase( name, parent ) -// { -// registerWrapper( viewKeyStruct::phasePVTParaFilesString(), &m_phasePVTParaFiles ). -// setInputFlag( InputFlags::REQUIRED ). -// setRestartFlags( RestartFlags::NO_WRITE ). -// setDescription( "Names of the files defining the parameters of the viscosity and density models" ); - -// registerWrapper( viewKeyStruct::flashModelParaFileString(), &m_flashModelParaFile ). -// setInputFlag( InputFlags::REQUIRED ). -// setRestartFlags( RestartFlags::NO_WRITE ). -// setDescription( "Name of the file defining the parameters of the flash model" ); -// } - -// template< typename P1DENS, typename P1VISC, typename P2DENS, typename P2VISC, typename FLASH > -// MultiPhaseMultiComponentFluid< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >:: -// ~MultiPhaseMultiComponentFluid() -// {} +template< typename P1DENS, typename P1VISC, typename P2DENS, typename P2VISC, typename FLASH > +MultiPhaseMultiComponentFluid< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >:: +MultiPhaseMultiComponentFluid( string const & name, Group * const parent ): + MultiFluidBase( name, parent ) +{ + registerWrapper( viewKeyStruct::phasePVTParaFilesString(), &m_phasePVTParaFiles ). + setInputFlag( InputFlags::REQUIRED ). + setRestartFlags( RestartFlags::NO_WRITE ). + setDescription( "Names of the files defining the parameters of the viscosity and density models" ); + + registerWrapper( viewKeyStruct::flashModelParaFileString(), &m_flashModelParaFile ). + setInputFlag( InputFlags::REQUIRED ). + setRestartFlags( RestartFlags::NO_WRITE ). + setDescription( "Name of the file defining the parameters of the flash model" ); +} template< typename P1DENS, typename P1VISC, typename P2DENS, typename P2VISC, typename FLASH > std::unique_ptr< ConstitutiveBase > @@ -231,6 +219,13 @@ void MultiPhaseMultiComponentFluid< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >::cre InputError ); } +// explicit instantiation of the model template; unfortunately we can't use CO2BrineFluid alias for this +template class MultiPhaseMultiComponentFluid< PVTProps::BrineCO2Density, + PVTProps::BrineViscosity, + PVTProps::SpanWagnerCO2Density, + PVTProps::FenghourCO2Viscosity, + PVTProps::CO2Solubility >; + REGISTER_CATALOG_ENTRY( ConstitutiveBase, CO2BrineFluid, string const &, Group * const ) } //namespace constitutive diff --git a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp index 8a6985744e4..d128cb9c48a 100644 --- a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp +++ b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp @@ -359,24 +359,6 @@ using CO2BrineFluid = MultiPhaseMultiComponentFluid< PVTProps::BrineCO2Density, PVTProps::FenghourCO2Viscosity, PVTProps::CO2Solubility >; -// The constructor is in the hpp for one reason: the testMultiFluid won't link if the constructor is in the cpp -// I could not find a workaround -template< typename P1DENS, typename P1VISC, typename P2DENS, typename P2VISC, typename FLASH > -MultiPhaseMultiComponentFluid< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >:: -MultiPhaseMultiComponentFluid( string const & name, Group * const parent ): - MultiFluidBase( name, parent ) -{ - registerWrapper( viewKeyStruct::phasePVTParaFilesString(), &m_phasePVTParaFiles ). - setInputFlag( dataRepository::InputFlags::REQUIRED ). - setRestartFlags( dataRepository::RestartFlags::NO_WRITE ). - setDescription( "Names of the files defining the parameters of the viscosity and density models" ); - - registerWrapper( viewKeyStruct::flashModelParaFileString(), &m_flashModelParaFile ). - setInputFlag( dataRepository::InputFlags::REQUIRED ). - setRestartFlags( dataRepository::RestartFlags::NO_WRITE ). - setDescription( "Name of the file defining the parameters of the flash model" ); -} - template< typename P1DENSWRAPPER, typename P1VISCWRAPPER, typename P2DENSWRAPPER, typename P2VISCWRAPPER, typename FLASHWRAPPER > GEOSX_HOST_DEVICE GEOSX_FORCE_INLINE From 7e054f0b2b7bd357689c5e1a9193df819f9019da Mon Sep 17 00:00:00 2001 From: Francois Hamon Date: Sat, 13 Mar 2021 09:47:46 -0800 Subject: [PATCH 09/10] addressed review comments --- .../constitutive/CMakeLists.txt | 20 ++++---- .../fluid/MultiPhaseMultiComponentFluid.cpp | 20 ++++---- .../fluid/MultiPhaseMultiComponentFluid.hpp | 18 ++++++-- ...ensityFunction.cpp => BrineCO2Density.cpp} | 22 +++++++-- ...ensityFunction.hpp => BrineCO2Density.hpp} | 2 +- ...scosityFunction.cpp => BrineViscosity.cpp} | 4 +- ...scosityFunction.hpp => BrineViscosity.hpp} | 2 +- ...lubilityFunction.cpp => CO2Solubility.cpp} | 46 ++++++++++++++----- ...lubilityFunction.hpp => CO2Solubility.hpp} | 6 ++- ...yFunction.cpp => FenghourCO2Viscosity.cpp} | 25 +++++++--- ...yFunction.hpp => FenghourCO2Viscosity.hpp} | 2 +- .../fluid/PVTFunctions/PVTFunctionHelpers.hpp | 44 ++++-------------- ...yFunction.cpp => SpanWagnerCO2Density.cpp} | 36 ++++++++++----- ...yFunction.hpp => SpanWagnerCO2Density.hpp} | 6 ++- .../unitTests/testCO2BrinePVTModels.cpp | 10 ++-- .../constitutive/unitTests/testMultiFluid.cpp | 6 --- 16 files changed, 157 insertions(+), 112 deletions(-) rename src/coreComponents/constitutive/fluid/PVTFunctions/{BrineCO2DensityFunction.cpp => BrineCO2Density.cpp} (88%) rename src/coreComponents/constitutive/fluid/PVTFunctions/{BrineCO2DensityFunction.hpp => BrineCO2Density.hpp} (99%) rename src/coreComponents/constitutive/fluid/PVTFunctions/{BrineViscosityFunction.cpp => BrineViscosity.cpp} (95%) rename src/coreComponents/constitutive/fluid/PVTFunctions/{BrineViscosityFunction.hpp => BrineViscosity.hpp} (99%) rename src/coreComponents/constitutive/fluid/PVTFunctions/{CO2SolubilityFunction.cpp => CO2Solubility.cpp} (89%) rename src/coreComponents/constitutive/fluid/PVTFunctions/{CO2SolubilityFunction.hpp => CO2Solubility.hpp} (98%) rename src/coreComponents/constitutive/fluid/PVTFunctions/{FenghourCO2ViscosityFunction.cpp => FenghourCO2Viscosity.cpp} (88%) rename src/coreComponents/constitutive/fluid/PVTFunctions/{FenghourCO2ViscosityFunction.hpp => FenghourCO2Viscosity.hpp} (99%) rename src/coreComponents/constitutive/fluid/PVTFunctions/{SpanWagnerCO2DensityFunction.cpp => SpanWagnerCO2Density.cpp} (91%) rename src/coreComponents/constitutive/fluid/PVTFunctions/{SpanWagnerCO2DensityFunction.hpp => SpanWagnerCO2Density.hpp} (95%) diff --git a/src/coreComponents/constitutive/CMakeLists.txt b/src/coreComponents/constitutive/CMakeLists.txt index c9b687e6b99..92105bec8a6 100644 --- a/src/coreComponents/constitutive/CMakeLists.txt +++ b/src/coreComponents/constitutive/CMakeLists.txt @@ -15,13 +15,13 @@ set( constitutive_headers contact/Coulomb.hpp fluid/DeadOilFluid.hpp fluid/MultiPhaseMultiComponentFluid.hpp - fluid/PVTFunctions/BrineCO2DensityFunction.hpp - fluid/PVTFunctions/BrineViscosityFunction.hpp - fluid/PVTFunctions/CO2SolubilityFunction.hpp - fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp + fluid/PVTFunctions/BrineCO2Density.hpp + fluid/PVTFunctions/BrineViscosity.hpp + fluid/PVTFunctions/CO2Solubility.hpp + fluid/PVTFunctions/FenghourCO2Viscosity.hpp fluid/PVTFunctions/FlashModelBase.hpp fluid/PVTFunctions/PVTFunctionBase.hpp - fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp + fluid/PVTFunctions/SpanWagnerCO2Density.hpp fluid/PVTFunctions/PVTFunctionHelpers.hpp fluid/SingleFluidBase.hpp fluid/singleFluidSelector.hpp @@ -76,11 +76,11 @@ set( constitutive_sources fluid/DeadOilFluid.cpp fluid/CompressibleSinglePhaseFluid.cpp fluid/MultiPhaseMultiComponentFluid.cpp - fluid/PVTFunctions/BrineCO2DensityFunction.cpp - fluid/PVTFunctions/BrineViscosityFunction.cpp - fluid/PVTFunctions/CO2SolubilityFunction.cpp - fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp - fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp + fluid/PVTFunctions/BrineCO2Density.cpp + fluid/PVTFunctions/BrineViscosity.cpp + fluid/PVTFunctions/CO2Solubility.cpp + fluid/PVTFunctions/FenghourCO2Viscosity.cpp + fluid/PVTFunctions/SpanWagnerCO2Density.cpp fluid/SingleFluidBase.cpp fluid/MultiFluidBase.cpp fluid/CompressibleSinglePhaseFluid.cpp diff --git a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp index 487c2481c72..0a3381d05b0 100644 --- a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp +++ b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.cpp @@ -146,12 +146,12 @@ void MultiPhaseMultiComponentFluid< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >::cre if( strs[0] == "DensityFun" ) { - if( strs[1] == "BrineCO2Density" ) + if( strs[1] == P1DENS::catalogName() ) { m_p1Density = std::make_unique< P1DENS >( strs, m_componentNames, m_componentMolarWeight ); m_p1DensityWrapper.emplace_back( m_p1Density->createKernelWrapper() ); } - else if( strs[1] == "SpanWagnerCO2Density" ) + else if( strs[1] == P2DENS::catalogName() ) { m_p2Density = std::make_unique< P2DENS >( strs, m_componentNames, m_componentMolarWeight ); m_p2DensityWrapper.emplace_back( m_p2Density->createKernelWrapper() ); @@ -159,12 +159,12 @@ void MultiPhaseMultiComponentFluid< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >::cre } else if( strs[0] == "ViscosityFun" ) { - if( strs[1] == "BrineViscosity" ) + if( strs[1] == P1VISC::catalogName() ) { m_p1Viscosity = std::make_unique< P1VISC >( strs, m_componentNames, m_componentMolarWeight ); m_p1ViscosityWrapper.emplace_back( m_p1Viscosity->createKernelWrapper() ); } - else if( strs[1] == "FenghourCO2Viscosity" ) + else if( strs[1] == P2VISC::catalogName() ) { m_p2Viscosity = std::make_unique< P2VISC >( strs, m_componentNames, m_componentMolarWeight ); m_p2ViscosityWrapper.emplace_back( m_p2Viscosity->createKernelWrapper() ); @@ -179,16 +179,16 @@ void MultiPhaseMultiComponentFluid< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >::cre } GEOSX_THROW_IF( m_p1Density == nullptr, - "BrineCO2Density model not found", + P1DENS::catalogName() << " model not found", InputError ); GEOSX_THROW_IF( m_p2Density == nullptr, - "SpanWagnerCO2Density model not found", + P2DENS::catalogName() << " model not found", InputError ); GEOSX_THROW_IF( m_p1Viscosity == nullptr, - "BrineViscosity model not found", + P1VISC::catalogName() << " model not found", InputError ); GEOSX_THROW_IF( m_p2Viscosity == nullptr, - "FenghourCO2Viscosity model not found", + P2VISC::catalogName() << " model not found", InputError ); // 2) Create the flash model @@ -201,7 +201,7 @@ void MultiPhaseMultiComponentFluid< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >::cre { string const str( buf ); string_array const strs = stringutilities::tokenize( str, " " ); - if( strs[0] == "FlashModel" && strs[1] == "CO2Solubility" ) + if( strs[0] == "FlashModel" && strs[1] == FLASH::catalogName() ) { m_flash = std::make_unique< FLASH >( strs, m_phaseNames, m_componentNames, m_componentMolarWeight ); m_flashWrapper.emplace_back( m_flash->createKernelWrapper() ); @@ -215,7 +215,7 @@ void MultiPhaseMultiComponentFluid< P1DENS, P1VISC, P2DENS, P2VISC, FLASH >::cre } GEOSX_THROW_IF( m_flash == nullptr, - "CO2Solubility model not found", + FLASH::catalogName() << " not found", InputError ); } diff --git a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp index d128cb9c48a..20053beda97 100644 --- a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp +++ b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp @@ -21,11 +21,11 @@ #include "constitutive/fluid/MultiFluidBase.hpp" #include "constitutive/fluid/MultiFluidUtils.hpp" -#include "constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp" -#include "constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp" -#include "constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp" -#include "constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp" -#include "constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/BrineCO2Density.hpp" +#include "constitutive/fluid/PVTFunctions/BrineViscosity.hpp" +#include "constitutive/fluid/PVTFunctions/CO2Solubility.hpp" +#include "constitutive/fluid/PVTFunctions/FenghourCO2Viscosity.hpp" +#include "constitutive/fluid/PVTFunctions/SpanWagnerCO2Density.hpp" #include @@ -335,6 +335,14 @@ class MultiPhaseMultiComponentFluid : public MultiFluidBase /// Pointer to the flash model std::unique_ptr< FLASH > m_flash; + // Note: here is the reason why I am storing **arrays of** wrappers instead of just storing wrappers + + // - If I store the wrappers here and pass them to the update class, then the total size of kernel arguments + // exceeds 4 KB, which the upper limit allowed by the compiler. + // - To circumvent this problem, I store **arrays of** wrappers here, and then I can pass the arrayViews + // to the kernel. In that case, the total size of kernel arguments is much smaller, so everything works fine. + // This workaround is a little bit odd, because it forces us to keep these arrays of size 1 here... + /// Pointer to the brine density model array1d< typename P1DENS::KernelWrapper > m_p1DensityWrapper; diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2Density.cpp similarity index 88% rename from src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp rename to src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2Density.cpp index 97dc30efec9..f0b6bccc3ee 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2Density.cpp @@ -13,10 +13,10 @@ */ /** - * @file BrineCO2DensityFunction.cpp + * @file BrineCO2Density.cpp */ -#include "constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/BrineCO2Density.hpp" #include "managers/Functions/FunctionManager.hpp" #include "managers/GeosxState.hpp" @@ -56,8 +56,24 @@ BrineCO2Density::BrineCO2Density( string_array const & inputPara, void BrineCO2Density::makeTable( string_array const & inputPara ) { + // initialize the (p,T) coordinates PTTableCoordinates tableCoords; - real64 const salinity = PVTFunctionHelpers::initializePropertyTableWithSalinity( inputPara, tableCoords ); + PVTFunctionHelpers::initializePropertyTable( inputPara, tableCoords ); + + // initialize salinity + GEOSX_THROW_IF( inputPara.size() < 9, + "Invalid property input!", + InputError ); + real64 salinity = 0.0; + try + { + salinity = stod( inputPara[8] ); + } + catch( const std::invalid_argument & e ) + { + GEOSX_THROW( "Invalid property argument:" + string( e.what()), + InputError ); + } array1d< real64 > densities( tableCoords.nPressures() * tableCoords.nTemperatures() ); calculateBrineDensity( tableCoords, salinity, densities ); diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2Density.hpp similarity index 99% rename from src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp rename to src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2Density.hpp index d95ffcfe6cd..f334e54320d 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2Density.hpp @@ -13,7 +13,7 @@ */ /** - * @file BrineCO2DensityFunction.hpp + * @file BrineCO2Density.hpp */ #ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINECO2DENSITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosity.cpp similarity index 95% rename from src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.cpp rename to src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosity.cpp index 579179dfb1d..69367e25dae 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosity.cpp @@ -13,10 +13,10 @@ */ /** - * @file BrineViscosityFunction.cpp + * @file BrineViscosity.cpp */ -#include "constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/BrineViscosity.hpp" namespace geosx { diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosity.hpp similarity index 99% rename from src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp rename to src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosity.hpp index 8a886184f96..48803aab25e 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosity.hpp @@ -13,7 +13,7 @@ */ /** - * @file BrineViscosityFunction.hpp + * @file BrineViscosity.hpp */ #ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_BRINEVISCOSITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2Solubility.cpp similarity index 89% rename from src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp rename to src/coreComponents/constitutive/fluid/PVTFunctions/CO2Solubility.cpp index 32f711f475c..30c3a9e5dba 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2Solubility.cpp @@ -13,10 +13,10 @@ */ /** - * @file CO2SolubilityFunction.cpp + * @file CO2Solubility.cpp */ -#include "constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/CO2Solubility.hpp" #include "constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp" #include "managers/Functions/FunctionManager.hpp" @@ -174,11 +174,33 @@ CO2Solubility::CO2Solubility( string_array const & inputPara, void CO2Solubility::makeTable( string_array const & inputPara ) { + // initialize the (p,T) coordinates PTTableCoordinates tableCoords; - real64 const salinity = PVTFunctionHelpers::initializePropertyTableWithSalinity( inputPara, tableCoords ); + PVTFunctionHelpers::initializePropertyTable( inputPara, tableCoords ); + + // initialize salinity and tolerance + GEOSX_THROW_IF( inputPara.size() < 9, + "Invalid property input!", + InputError ); + + real64 tolerance = 1e-9; + real64 salinity = 0.0; + try + { + salinity = stod( inputPara[8] ); + if( inputPara.size() >= 10 ) + { + tolerance = stod( inputPara[9] ); + } + } + catch( const std::invalid_argument & e ) + { + GEOSX_THROW( "Invalid property argument:" + string( e.what()), + InputError ); + } array1d< real64 > values( tableCoords.nPressures() * tableCoords.nTemperatures() ); - calculateCO2Solubility( tableCoords, salinity, values ); + calculateCO2Solubility( tolerance, tableCoords, salinity, values ); FunctionManager & functionManager = getGlobalState().getFunctionManager(); m_CO2SolubilityTable = dynamicCast< TableFunction * >( functionManager.createChild( "TableFunction", "CO2SolubilityTable" ) ); @@ -188,7 +210,8 @@ void CO2Solubility::makeTable( string_array const & inputPara ) m_CO2SolubilityTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); } -void CO2Solubility::calculateCO2Solubility( PTTableCoordinates const & tableCoords, +void CO2Solubility::calculateCO2Solubility( real64 const & tolerance, + PTTableCoordinates const & tableCoords, real64 const & salinity, array1d< real64 > const & values ) { @@ -212,7 +235,7 @@ void CO2Solubility::calculateCO2Solubility( PTTableCoordinates const & tableCoor // compute reduced volume by solving the CO2 equation of state real64 V_r = 0.0; - CO2SolubilityFunction( T, P, V_r, &detail::ff ); + CO2SolubilityFunction( tolerance, T, P, V_r, &detail::ff ); // compute equation (6) of Duan and Sun (2003) real64 const logK = detail::Par( T+T_K_f, P, mu ) @@ -222,18 +245,17 @@ void CO2Solubility::calculateCO2Solubility( PTTableCoordinates const & tableCoor // mole fraction of CO2 in vapor phase, equation (4) of Duan and Sun (2003) real64 const y_CO2 = (P - detail::PWater( T ))/P; - values[j*tableCoords.nPressures()+i] = y_CO2 * P / exp( logK ); + values[j*nPressures+i] = y_CO2 * P / exp( logK ); } } } -void CO2Solubility::CO2SolubilityFunction( real64 const & T, +void CO2Solubility::CO2SolubilityFunction( real64 const & tolerance, + real64 const & T, real64 const & P, real64 & V_r, real64 (*f)( real64 const & x1, real64 const & x2, real64 const & x3 ) ) { - - constexpr real64 eps = 1e-9; constexpr real64 dx = 1e-10; int count = 0; real64 Vr_int = 0.05; @@ -253,13 +275,13 @@ void CO2Solubility::CO2SolubilityFunction( real64 const & T, real64 const v1 = (*f)( T, P, V_r+dx ); real64 const dre = -v0/((v1-v0)/dx); - if( fabs( dre ) < eps ) + if( fabs( dre ) < tolerance ) { break; } GEOSX_THROW_IF( count > 50, - "CO2Solubility NR convergence fails! " << "dre = " << dre << ", eps = " << eps, + "CO2Solubility NR convergence fails! " << "dre = " << dre << ", tolerance = " << tolerance, InputError ); count++; diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2Solubility.hpp similarity index 98% rename from src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp rename to src/coreComponents/constitutive/fluid/PVTFunctions/CO2Solubility.hpp index 1d75b488603..b99bcf04197 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2Solubility.hpp @@ -128,11 +128,13 @@ class CO2Solubility : public FlashModelBase void makeTable( string_array const & inputPara ); - void calculateCO2Solubility( PVTProps::PTTableCoordinates const & tableCoords, + void calculateCO2Solubility( real64 const & tolerance, + PVTProps::PTTableCoordinates const & tableCoords, real64 const & salinity, array1d< real64 > const & values ); - void CO2SolubilityFunction( real64 const & T, + void CO2SolubilityFunction( real64 const & tolerance, + real64 const & T, real64 const & P, real64 & V_r, real64 (*f)( real64 const & x1, real64 const & x2, real64 const & x3 ) ); diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2Viscosity.cpp similarity index 88% rename from src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp rename to src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2Viscosity.cpp index d6e27f684f7..289ba4f9902 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2Viscosity.cpp @@ -13,12 +13,12 @@ */ /** - * @file FenghourCO2ViscosityFunction.cpp + * @file FenghourCO2Viscosity.cpp */ -#include "constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/FenghourCO2Viscosity.hpp" -#include "constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/SpanWagnerCO2Density.hpp" #include "managers/Functions/FunctionManager.hpp" #include "managers/GeosxState.hpp" @@ -43,15 +43,28 @@ FenghourCO2Viscosity::FenghourCO2Viscosity( string_array const & inputPara, void FenghourCO2Viscosity::makeTable( string_array const & inputPara ) { - localIndex const expectedNumParameters = 8; PTTableCoordinates tableCoords; - PVTFunctionHelpers::initializePropertyTable( inputPara, expectedNumParameters, tableCoords ); + PVTFunctionHelpers::initializePropertyTable( inputPara, tableCoords ); + + real64 tolerance = 1e-10; + try + { + if( inputPara.size() >= 9 ) + { + tolerance = stod( inputPara[8] ); + } + } + catch( const std::invalid_argument & e ) + { + GEOSX_THROW( "Invalid property argument:" + string( e.what()), + InputError ); + } localIndex const nP = tableCoords.nPressures(); localIndex const nT = tableCoords.nTemperatures(); array1d< real64 > density( nP * nT ); array1d< real64 > viscosity( nP * nT ); - SpanWagnerCO2Density::calculateCO2Density( tableCoords, density ); + SpanWagnerCO2Density::calculateCO2Density( tolerance, tableCoords, density ); calculateCO2Viscosity( tableCoords, density, viscosity ); FunctionManager & functionManager = getGlobalState().getFunctionManager(); diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2Viscosity.hpp similarity index 99% rename from src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp rename to src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2Viscosity.hpp index bef04c8d5e3..51910b75a62 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2Viscosity.hpp @@ -13,7 +13,7 @@ */ /** - * @file FenghourCO2ViscosityFunction.hpp + * @file FenghourCO2Viscosity.hpp */ #ifndef GEOSX_CONSTITUTIVE_FLUID_PVTFUNCTIONS_FENGHOURCO2VISCOSITY_HPP_ diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp index a2d3593c48a..687979aa471 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionHelpers.hpp @@ -61,6 +61,8 @@ struct PVTFunctionHelpers /** * @brief Look for the expectedNames in the names provided by the user + * @tparam InputRange type of the input range + * @tparam ExpectedRange type of the expected range * @param[in] inputNames phase or component names provided by the user * @param[in] expectedNames expected names that can be accepted by GEOSX * @return the index of the phase or component that was found @@ -82,52 +84,24 @@ struct PVTFunctionHelpers * @param[in] inputParameters the strings reads in the file provided by the user * @param[inout] tableCoords the (p,T) coordinates of the table */ - static real64 - initializePropertyTableWithSalinity( string_array const & inputParameters, - PTTableCoordinates & tableCoords ) - { - localIndex const expectedNumParameters = 9; - real64 salinity = 0.0; - initializePropertyTable( inputParameters, expectedNumParameters, tableCoords ); - try - { - salinity = stod( inputParameters[8] ); - } - catch( const std::invalid_argument & e ) - { - GEOSX_THROW( "Invalid property argument:" + string( e.what()), - InputError ); - } - return salinity; - } - - /** - * @brief Populate the coordinate table with pressure and temperature - * @param[in] inputParameters the strings reads in the file provided by the user - * @param[in] expectedNumParameters the number of expected parameters in the file provided by the user - * @param[inout] tableCoords the (p,T) coordinates of the table - */ static void initializePropertyTable( string_array const & inputParameters, - localIndex const expectedNumParameters, PTTableCoordinates & tableCoords ) { - real64 TStart, TEnd, dT, PStart, PEnd, dP; - - GEOSX_THROW_IF( inputParameters.size() != expectedNumParameters, + GEOSX_THROW_IF( inputParameters.size() < 8, "Invalid property input!", InputError ); try { - PStart = stod( inputParameters[2] ); - PEnd = stod( inputParameters[3] ); - dP = stod( inputParameters[4] ); + real64 const PStart = stod( inputParameters[2] ); + real64 const PEnd = stod( inputParameters[3] ); + real64 const dP = stod( inputParameters[4] ); - TStart = stod( inputParameters[5] ); - TEnd = stod( inputParameters[6] ); - dT = stod( inputParameters[7] ); + real64 const TStart = stod( inputParameters[5] ); + real64 const TEnd = stod( inputParameters[6] ); + real64 const dT = stod( inputParameters[7] ); for( real64 P = PStart; P <= PEnd; P += dP ) { diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2Density.cpp similarity index 91% rename from src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp rename to src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2Density.cpp index a29bd62fdff..881024e0eb3 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.cpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2Density.cpp @@ -13,10 +13,10 @@ */ /** - * @file SpanWagnerCO2DensityFunction.cpp + * @file SpanWagnerCO2Density.cpp */ -#include "constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/SpanWagnerCO2Density.hpp" #include "managers/Functions/FunctionManager.hpp" #include "managers/GeosxState.hpp" @@ -157,12 +157,25 @@ SpanWagnerCO2Density::SpanWagnerCO2Density( string_array const & inputPara, void SpanWagnerCO2Density::makeTable( string_array const & inputPara ) { - localIndex const expectedNumParameters = 8; PTTableCoordinates tableCoords; - PVTFunctionHelpers::initializePropertyTable( inputPara, expectedNumParameters, tableCoords ); + PVTFunctionHelpers::initializePropertyTable( inputPara, tableCoords ); + + real64 tolerance = 1e-10; + try + { + if( inputPara.size() >= 9 ) + { + tolerance = stod( inputPara[8] ); + } + } + catch( const std::invalid_argument & e ) + { + GEOSX_THROW( "Invalid property argument:" + string( e.what()), + InputError ); + } array1d< real64 > densities( tableCoords.nPressures() * tableCoords.nTemperatures() ); - calculateCO2Density( tableCoords, densities ); + calculateCO2Density( tolerance, tableCoords, densities ); FunctionManager & functionManager = getGlobalState().getFunctionManager(); m_CO2DensityTable = dynamicCast< TableFunction * >( functionManager.createChild( "TableFunction", "CO2DensityTable" ) ); @@ -173,7 +186,8 @@ void SpanWagnerCO2Density::makeTable( string_array const & inputPara ) } -void SpanWagnerCO2Density::calculateCO2Density( PTTableCoordinates const & tableCoords, +void SpanWagnerCO2Density::calculateCO2Density( real64 const & tolerance, + PTTableCoordinates const & tableCoords, array1d< real64 > const & densities ) { @@ -188,12 +202,13 @@ void SpanWagnerCO2Density::calculateCO2Density( PTTableCoordinates const & table for( localIndex j = 0; j < nTemperatures; ++j ) { real64 const TK = tableCoords.getTemperature( j ) + TK_f; - spanWagnerCO2DensityFunction( TK, PPa, densities[j*nPressures+i], &detail::f ); + spanWagnerCO2DensityFunction( tolerance, TK, PPa, densities[j*nPressures+i], &detail::f ); } } } -void SpanWagnerCO2Density::spanWagnerCO2DensityFunction( real64 const & T, +void SpanWagnerCO2Density::spanWagnerCO2DensityFunction( real64 const & tolerance, + real64 const & T, real64 const & P, real64 & rho, real64 (*f)( real64 const & x1, real64 const & x2, real64 const & x3 ) ) @@ -210,7 +225,6 @@ void SpanWagnerCO2Density::spanWagnerCO2DensityFunction( real64 const & T, constexpr real64 lda[] = { 1.9245108, -0.62385555, -0.32731127, 0.39245142 }; constexpr real64 ldt[] = { 0.340, 0.5, 1.6666666667, 1.833333333 }; - real64 const eps = 1e-10; real64 const dx = 1e-10; int count = 0; @@ -251,12 +265,12 @@ void SpanWagnerCO2Density::spanWagnerCO2DensityFunction( real64 const & T, real64 const v0 = (*f)( T, P, rho ); real64 const v1 = (*f)( T, P, rho+dx ); real64 const dre = -v0/((v1-v0)/dx); - if( fabs( dre ) < eps ) + if( fabs( dre ) < tolerance ) { break; } - GEOSX_ERROR_IF( count > 50, "SpanWagnerCO2Density NR convergence fails! " << "dre = " << dre << ", eps = " << eps ); + GEOSX_ERROR_IF( count > 50, "SpanWagnerCO2Density NR convergence fails! " << "dre = " << dre << ", tolerance = " << tolerance ); count++; rho += dre; diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2Density.hpp similarity index 95% rename from src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp rename to src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2Density.hpp index 1db2563cf37..fb921ff8a8e 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2Density.hpp @@ -109,7 +109,8 @@ class SpanWagnerCO2Density : public PVTFunctionBase KernelWrapper createKernelWrapper(); static - void calculateCO2Density( PVTProps::PTTableCoordinates const & tableCoords, + void calculateCO2Density( real64 const & tolerance, + PVTProps::PTTableCoordinates const & tableCoords, array1d< real64 > const & densities ); private: @@ -117,7 +118,8 @@ class SpanWagnerCO2Density : public PVTFunctionBase void makeTable( string_array const & inputPara ); static - void spanWagnerCO2DensityFunction( real64 const & T, + void spanWagnerCO2DensityFunction( real64 const & tolerance, + real64 const & T, real64 const & P, real64 & rho, real64 (*f)( real64 const & x1, real64 const & x2, real64 const & x3 ) ); diff --git a/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp b/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp index 48aeba06f30..1e3077ba481 100644 --- a/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp +++ b/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp @@ -17,11 +17,11 @@ #include "common/DataTypes.hpp" #include "common/TimingMacros.hpp" #include "constitutive/fluid/multiFluidSelector.hpp" -#include "constitutive/fluid/PVTFunctions/BrineViscosityFunction.hpp" -#include "constitutive/fluid/PVTFunctions/FenghourCO2ViscosityFunction.hpp" -#include "constitutive/fluid/PVTFunctions/BrineCO2DensityFunction.hpp" -#include "constitutive/fluid/PVTFunctions/SpanWagnerCO2DensityFunction.hpp" -#include "constitutive/fluid/PVTFunctions/CO2SolubilityFunction.hpp" +#include "constitutive/fluid/PVTFunctions/BrineViscosity.hpp" +#include "constitutive/fluid/PVTFunctions/FenghourCO2Viscosity.hpp" +#include "constitutive/fluid/PVTFunctions/BrineCO2Density.hpp" +#include "constitutive/fluid/PVTFunctions/SpanWagnerCO2Density.hpp" +#include "constitutive/fluid/PVTFunctions/CO2Solubility.hpp" #include "managers/GeosxState.hpp" #include "managers/initialization.hpp" diff --git a/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp b/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp index e8ba1169ec6..3f10b6215b3 100644 --- a/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp +++ b/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp @@ -801,12 +801,6 @@ TEST_F( DeadOilFluidFromTableTest, numericalDerivativesMolar ) } } -template class MultiPhaseMultiComponentFluid< PVTProps::BrineCO2Density, - PVTProps::BrineViscosity, - PVTProps::SpanWagnerCO2Density, - PVTProps::FenghourCO2Viscosity, - PVTProps::CO2Solubility >; - MultiFluidBase & makeMultiPhaseMultiComponentFluid( string const & name, Group * parent ) { CO2BrineFluid & fluid = parent->registerGroup< CO2BrineFluid >( name ); From 2a038ad3548fc77b5aeec138e27738bfe4cc09a6 Mon Sep 17 00:00:00 2001 From: Francois Hamon Date: Wed, 17 Mar 2021 18:43:54 -0700 Subject: [PATCH 10/10] updated integratedTests submodule --- integratedTests | 2 +- .../constitutive/fluid/DeadOilFluid.hpp | 2 +- .../fluid/MultiFluidPVTPackageWrapper.cpp | 4 +- .../fluid/MultiFluidPVTPackageWrapper.hpp | 4 -- .../fluid/MultiPhaseMultiComponentFluid.hpp | 36 ++++++------ .../fluid/PVTFunctions/BrineCO2Density.hpp | 42 ++++++++------ .../fluid/PVTFunctions/BrineViscosity.hpp | 16 +++++- .../fluid/PVTFunctions/CO2Solubility.hpp | 11 ++-- .../PVTFunctions/FenghourCO2Viscosity.hpp | 15 ++++- .../fluid/PVTFunctions/PVTFunctionBase.hpp | 7 ++- .../PVTFunctions/SpanWagnerCO2Density.hpp | 15 ++++- .../unitTests/testCO2BrinePVTModels.cpp | 55 ++++++++++++------- .../constitutive/unitTests/testMultiFluid.cpp | 45 +++++++++------ .../co2_hybrid_1d.xml | 2 +- .../staircase_co2_wells_3d.xml | 6 +- .../staircase_co2_wells_hybrid_3d.xml | 4 +- 16 files changed, 166 insertions(+), 100 deletions(-) diff --git a/integratedTests b/integratedTests index d977a52535e..aae94aa3f94 160000 --- a/integratedTests +++ b/integratedTests @@ -1 +1 @@ -Subproject commit d977a52535ea595195cb6350694b77ad910a236e +Subproject commit aae94aa3f94c49763cf4b3ec42e98bd61d707d98 diff --git a/src/coreComponents/constitutive/fluid/DeadOilFluid.hpp b/src/coreComponents/constitutive/fluid/DeadOilFluid.hpp index 114a1d6edca..98054345064 100644 --- a/src/coreComponents/constitutive/fluid/DeadOilFluid.hpp +++ b/src/coreComponents/constitutive/fluid/DeadOilFluid.hpp @@ -704,7 +704,7 @@ void DeadOilFluidUpdate::compute( real64 pressure, dPhaseFraction_dPressure[ip] = 0.0; for( localIndex ic = 0; ic < nComps; ++ic ) { - dPhaseFraction_dGlobalCompFraction[ip][ic] = (ip == ic) ? 1-composition[ip] : -composition[ip]; + dPhaseFraction_dGlobalCompFraction[ip][ic] = (ip == ic) ? 1.0 : 0.0; phaseCompFraction[ip][ic] = (ip == ic) ? 1.0 : 0.0; dPhaseCompFraction_dPressure[ip][ic] = 0.0; diff --git a/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.cpp b/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.cpp index 27b241380c9..25d60bd7467 100644 --- a/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.cpp +++ b/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.cpp @@ -92,7 +92,7 @@ void MultiFluidPVTPackageWrapperUpdate::compute( real64 pressure, arraySlice2d< real64 > const & phaseCompFrac, real64 & totalDens ) const { -#ifdef __CUDACC__ +#if defined(__CUDA_ARCH__) GEOSX_ERROR( "This function cannot be used on GPU" ); #else localIndex const NC = m_componentMolarWeight.size(); @@ -231,7 +231,7 @@ void MultiFluidPVTPackageWrapperUpdate::compute( real64 pressure, real64 & dTotalDensity_dTemperature, arraySlice1d< real64 > const & dTotalDensity_dGlobalCompFraction ) const { -#ifdef __CUDACC__ +#if defined(__CUDA_ARCH__) GEOSX_ERROR( "This function cannot be used on GPU" ); #else // 0. make shortcut structs to avoid long names (TODO maybe remove) diff --git a/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.hpp b/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.hpp index 27444505100..a5664f38b21 100644 --- a/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.hpp +++ b/src/coreComponents/constitutive/fluid/MultiFluidPVTPackageWrapper.hpp @@ -165,9 +165,6 @@ class MultiFluidPVTPackageWrapperUpdate final : public MultiFluidBaseUpdate real64 const temperature, arraySlice1d< real64 const > const & composition ) const override { -#ifdef __CUDACC__ - GEOSX_ERROR( "This function cannot be used on GPU" ); -#else compute( pressure, temperature, composition, @@ -195,7 +192,6 @@ class MultiFluidPVTPackageWrapperUpdate final : public MultiFluidBaseUpdate m_dTotalDensity_dPressure[k][q], m_dTotalDensity_dTemperature[k][q], m_dTotalDensity_dGlobalCompFraction[k][q] ); -#endif } private: diff --git a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp index 20053beda97..7b27f0b3191 100644 --- a/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp +++ b/src/coreComponents/constitutive/fluid/MultiPhaseMultiComponentFluid.hpp @@ -443,23 +443,23 @@ compute( real64 pressure, m_p1DensityWrapper[0].compute( pressure, temperatureInCelsius, - phaseCompFraction[ip1], + phaseCompFraction[ip1], dPhaseCompFrac_dPres[ip1], dPhaseCompFrac_dTemp[ip1], dPhaseCompFrac_dComp[ip1], phaseDensity[ip1], dPhaseDens_dPres, dPhaseDens_dTemp, dPhaseDens_dComp, m_useMass ); m_p1ViscosityWrapper[0].compute( pressure, temperatureInCelsius, - phaseCompFraction[ip1], + phaseCompFraction[ip1], dPhaseCompFrac_dPres[ip1], dPhaseCompFrac_dTemp[ip1], dPhaseCompFrac_dComp[ip1], phaseViscosity[ip1], dPhaseVisc_dPres, dPhaseVisc_dTemp, dPhaseVisc_dComp, m_useMass ); m_p2DensityWrapper[0].compute( pressure, temperatureInCelsius, - phaseCompFraction[ip2], + phaseCompFraction[ip2], dPhaseCompFrac_dPres[ip2], dPhaseCompFrac_dTemp[ip2], dPhaseCompFrac_dComp[ip2], phaseDensity[ip2], dPhaseDens_dPres, dPhaseDens_dTemp, dPhaseDens_dComp, m_useMass ); m_p2ViscosityWrapper[0].compute( pressure, temperatureInCelsius, - phaseCompFraction[ip2], + phaseCompFraction[ip2], dPhaseCompFrac_dPres[ip2], dPhaseCompFrac_dTemp[ip2], dPhaseCompFrac_dComp[ip2], phaseViscosity[ip2], dPhaseVisc_dPres, dPhaseVisc_dTemp, dPhaseVisc_dComp, m_useMass ); @@ -482,14 +482,14 @@ compute( real64 pressure, stackArray1d< real64, numComps > dPhaseMolarDens_dComp( 2 ); m_p1DensityWrapper[0].compute( pressure, temperatureInCelsius, - phaseCompFraction[ip1], + phaseCompFraction[ip1], dPhaseCompFrac_dPres[ip1], dPhaseCompFrac_dTemp[ip1], dPhaseCompFrac_dComp[ip1], phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, 0 ); phaseMW[ip1] = phaseDensity[ip1] / phaseMolarDens; m_p2DensityWrapper[0].compute( pressure, temperatureInCelsius, - phaseCompFraction[ip2], + phaseCompFraction[ip2], dPhaseCompFrac_dPres[ip2], dPhaseCompFrac_dTemp[ip2], dPhaseCompFrac_dComp[ip2], phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, 0 ); phaseMW[ip2] = phaseDensity[ip2] / phaseMolarDens; @@ -528,13 +528,15 @@ compute( real64 pressure, // for now, we have to compute the phase mass density here m_p1DensityWrapper[0].compute( pressure, temperatureInCelsius, - phaseCompFraction[ip1], + phaseCompFraction[ip1], dPhaseCompFrac_dPres[ip1], + dPhaseCompFrac_dTemp[ip1], dPhaseCompFrac_dComp[ip1], phaseMassDensity[ip1], dPhaseMassDens_dPres, dPhaseMassDens_dTemp, dPhaseMassDens_dComp, true ); m_p2DensityWrapper[0].compute( pressure, temperatureInCelsius, - phaseCompFraction[ip2], + phaseCompFraction[ip2], dPhaseCompFrac_dPres[ip2], + dPhaseCompFrac_dTemp[ip2], dPhaseCompFrac_dComp[ip2], phaseMassDensity[ip2], dPhaseMassDens_dPres, dPhaseMassDens_dTemp, dPhaseMassDens_dComp, true ); @@ -691,22 +693,22 @@ compute( real64 pressure, m_p1DensityWrapper[0].compute( pressure, temperatureInCelsius, - phaseCompFrac.value[ip1], + phaseCompFrac.value[ip1], phaseCompFrac.dPres[ip1], phaseCompFrac.dTemp[ip1], phaseCompFrac.dComp[ip1], phaseDens.value[ip1], phaseDens.dPres[ip1], phaseDens.dTemp[ip1], phaseDens.dComp[ip1], m_useMass ); m_p1ViscosityWrapper[0].compute( pressure, temperatureInCelsius, - phaseCompFrac.value[ip1], + phaseCompFrac.value[ip1], phaseCompFrac.dPres[ip1], phaseCompFrac.dTemp[ip1], phaseCompFrac.dComp[ip1], phaseVisc.value[ip1], phaseVisc.dPres[ip1], phaseVisc.dTemp[ip1], phaseVisc.dComp[ip1], m_useMass ); m_p2DensityWrapper[0].compute( pressure, temperatureInCelsius, - phaseCompFrac.value[ip2], + phaseCompFrac.value[ip2], phaseCompFrac.dPres[ip2], phaseCompFrac.dTemp[ip2], phaseCompFrac.dComp[ip2], phaseDens.value[ip2], phaseDens.dPres[ip2], phaseDens.dTemp[ip2], phaseDens.dComp[ip2], m_useMass ); m_p2ViscosityWrapper[0].compute( pressure, temperatureInCelsius, - phaseCompFrac.value[ip2], + phaseCompFrac.value[ip2], phaseCompFrac.dPres[ip2], phaseCompFrac.dTemp[ip2], phaseCompFrac.dComp[ip2], phaseVisc.value[ip2], phaseVisc.dPres[ip2], phaseVisc.dTemp[ip2], phaseVisc.dComp[ip2], m_useMass ); @@ -735,7 +737,7 @@ compute( real64 pressure, stackArray1d< real64, numComps > dPhaseMolarDens_dComp( 2 ); m_p2DensityWrapper[0].compute( pressure, temperatureInCelsius, - phaseCompFrac.value[ip2], + phaseCompFrac.value[ip2], phaseCompFrac.dPres[ip2], phaseCompFrac.dTemp[ip2], phaseCompFrac.dComp[ip2], phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, 0 ); phaseMW[ip2] = phaseDens.value[ip2] / phaseMolarDens; @@ -747,7 +749,7 @@ compute( real64 pressure, } m_p1DensityWrapper[0].compute( pressure, temperatureInCelsius, - phaseCompFrac.value[ip1], + phaseCompFrac.value[ip1], phaseCompFrac.dPres[ip1], phaseCompFrac.dTemp[ip1], phaseCompFrac.dComp[ip1], phaseMolarDens, dPhaseMolarDens_dPres, dPhaseMolarDens_dTemp, dPhaseMolarDens_dComp, 0 ); phaseMW[ip1] = phaseDens.value[ip1] / phaseMolarDens; @@ -847,13 +849,15 @@ compute( real64 pressure, // for now, we have to compute the phase mass density here m_p1DensityWrapper[0].compute( pressure, temperatureInCelsius, - phaseCompFrac.value[ip1], + phaseCompFrac.value[ip1], phaseCompFrac.dPres[ip1], + phaseCompFrac.dTemp[ip1], phaseCompFrac.dComp[ip1], phaseMassDens.value[ip1], phaseMassDens.dPres[ip1], phaseMassDens.dTemp[ip1], phaseMassDens.dComp[ip1], true ); m_p2DensityWrapper[0].compute( pressure, temperatureInCelsius, - phaseCompFrac.value[ip2], + phaseCompFrac.value[ip2], phaseCompFrac.dPres[ip2], + phaseCompFrac.dTemp[ip2], phaseCompFrac.dComp[ip2], phaseMassDens.value[ip2], phaseMassDens.dPres[ip2], phaseMassDens.dTemp[ip2], phaseMassDens.dComp[ip2], true ); diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2Density.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2Density.hpp index f334e54320d..81ac0819dcc 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2Density.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineCO2Density.hpp @@ -66,10 +66,13 @@ class BrineCO2DensityUpdate final : public PVTFunctionBaseUpdate virtual void compute( real64 const & pressure, real64 const & temperature, arraySlice1d< real64 const > const & phaseComposition, + arraySlice1d< real64 const > const & dPhaseComposition_dPressure, + arraySlice1d< real64 const > const & dPhaseComposition_dTemperature, + arraySlice2d< real64 const > const & dPhaseComposition_dGlobalCompFraction, real64 & value, real64 & dValue_dPressure, real64 & dValue_dTemperature, - arraySlice1d< real64 > const & dValue_dPhaseComposition, + arraySlice1d< real64 > const & dValue_dGlobalCompFraction, bool useMass = 0 ) const override; protected: @@ -138,10 +141,13 @@ GEOSX_FORCE_INLINE void BrineCO2DensityUpdate::compute( real64 const & pressure, real64 const & temperature, arraySlice1d< real64 const > const & phaseComposition, + arraySlice1d< real64 const > const & dPhaseComposition_dPressure, + arraySlice1d< real64 const > const & dPhaseComposition_dTemperature, + arraySlice2d< real64 const > const & dPhaseComposition_dGlobalCompFraction, real64 & value, real64 & dValue_dPressure, real64 & dValue_dTemperature, - arraySlice1d< real64 > const & dValue_dPhaseComposition, + arraySlice1d< real64 > const & dValue_dGlobalCompFraction, bool useMass ) const { // this method implements the method proposed by E. Garcia (2001) @@ -168,15 +174,19 @@ void BrineCO2DensityUpdate::compute( real64 const & pressure, + 3 * d * squaredTemp ) * 1e-6; // CO2 concentration - real64 const denom = ( m_componentMolarWeight[m_waterIndex] * ( 1.0 - phaseComposition[m_CO2Index] ) ); - real64 const coef = phaseComposition[m_CO2Index] / denom; + real64 const wMwInv = 1.0 / m_componentMolarWeight[m_waterIndex]; + real64 const oneMinusCO2PhaseCompInv = 1.0 / ( 1.0 - phaseComposition[m_CO2Index] ); + real64 const oneMinusCO2PhaseCompInvSquared = oneMinusCO2PhaseCompInv * oneMinusCO2PhaseCompInv; + real64 const coef = wMwInv * phaseComposition[m_CO2Index] * oneMinusCO2PhaseCompInv; + real64 const dCoef_dPres = wMwInv * dPhaseComposition_dPressure[m_CO2Index] * oneMinusCO2PhaseCompInvSquared; + real64 const dCoef_dTemp = wMwInv * dPhaseComposition_dTemperature[m_CO2Index] * oneMinusCO2PhaseCompInvSquared; real64 dCoef_dComp[2]{}; - dCoef_dComp[m_CO2Index] = 1.0 / denom; - dCoef_dComp[m_waterIndex] = -m_componentMolarWeight[m_waterIndex] * phaseComposition[m_CO2Index] / (denom * denom); + dCoef_dComp[m_CO2Index] = wMwInv * dPhaseComposition_dGlobalCompFraction[m_CO2Index][m_CO2Index] * oneMinusCO2PhaseCompInvSquared; + dCoef_dComp[m_waterIndex] = wMwInv * dPhaseComposition_dGlobalCompFraction[m_CO2Index][m_waterIndex] * oneMinusCO2PhaseCompInvSquared; real64 const conc = coef * density; - real64 const dConc_dPres = coef * densityDeriv[0]; - real64 const dConc_dTemp = coef * densityDeriv[1]; + real64 const dConc_dPres = dCoef_dPres * density + coef * densityDeriv[0]; + real64 const dConc_dTemp = dCoef_dTemp * density + coef * densityDeriv[1]; real64 dConc_dComp[2]{}; dConc_dComp[m_CO2Index] = dCoef_dComp[m_CO2Index] * density; dConc_dComp[m_waterIndex] = dCoef_dComp[m_waterIndex] * density; @@ -203,10 +213,10 @@ void BrineCO2DensityUpdate::compute( real64 const & pressure, dValue_dTemperature = densityDeriv[1] + m_componentMolarWeight[m_CO2Index] * dConc_dTemp - dConcDensVol_dTemp; - dValue_dPhaseComposition[m_CO2Index] = m_componentMolarWeight[m_CO2Index] * dConc_dComp[m_CO2Index] - - dConcDensVol_dComp[m_CO2Index]; - dValue_dPhaseComposition[m_waterIndex] = m_componentMolarWeight[m_CO2Index] * dConc_dComp[m_waterIndex] - - dConcDensVol_dComp[m_waterIndex]; + dValue_dGlobalCompFraction[m_CO2Index] = m_componentMolarWeight[m_CO2Index] * dConc_dComp[m_CO2Index] + - dConcDensVol_dComp[m_CO2Index]; + dValue_dGlobalCompFraction[m_waterIndex] = m_componentMolarWeight[m_CO2Index] * dConc_dComp[m_waterIndex] + - dConcDensVol_dComp[m_waterIndex]; } else { @@ -219,10 +229,10 @@ void BrineCO2DensityUpdate::compute( real64 const & pressure, dValue_dTemperature = densityDeriv[1] / m_componentMolarWeight[m_waterIndex] + dConc_dTemp - dConcDensVol_dTemp / m_componentMolarWeight[m_waterIndex]; - dValue_dPhaseComposition[m_CO2Index] = dConc_dComp[m_CO2Index] - - dConcDensVol_dComp[m_CO2Index] / m_componentMolarWeight[m_waterIndex]; - dValue_dPhaseComposition[m_waterIndex] = dConc_dComp[m_waterIndex] - - dConcDensVol_dComp[m_waterIndex] / m_componentMolarWeight[m_waterIndex]; + dValue_dGlobalCompFraction[m_CO2Index] = dConc_dComp[m_CO2Index] + - dConcDensVol_dComp[m_CO2Index] / m_componentMolarWeight[m_waterIndex]; + dValue_dGlobalCompFraction[m_waterIndex] = dConc_dComp[m_waterIndex] + - dConcDensVol_dComp[m_waterIndex] / m_componentMolarWeight[m_waterIndex]; } } diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosity.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosity.hpp index 48803aab25e..09e56cd6ad2 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosity.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/BrineViscosity.hpp @@ -61,10 +61,13 @@ class BrineViscosityUpdate final : public PVTFunctionBaseUpdate virtual void compute( real64 const & pressure, real64 const & temperature, arraySlice1d< real64 const > const & phaseComposition, + arraySlice1d< real64 const > const & dPhaseComposition_dPressure, + arraySlice1d< real64 const > const & dPhaseComposition_dTemperature, + arraySlice2d< real64 const > const & dPhaseComposition_dGlobalCompFraction, real64 & value, real64 & dValue_dPressure, real64 & dValue_dTemperature, - arraySlice1d< real64 > const & dValue_dPhaseComposition, + arraySlice1d< real64 > const & dValue_dGlobalCompFraction, bool useMass = 0 ) const override; protected: @@ -119,20 +122,27 @@ GEOSX_FORCE_INLINE void BrineViscosityUpdate::compute( real64 const & pressure, real64 const & temperature, arraySlice1d< real64 const > const & phaseComposition, + arraySlice1d< real64 const > const & dPhaseComposition_dPressure, + arraySlice1d< real64 const > const & dPhaseComposition_dTemperature, + arraySlice2d< real64 const > const & dPhaseComposition_dGlobalCompFraction, real64 & value, real64 & dValue_dPressure, real64 & dValue_dTemperature, - arraySlice1d< real64 > const & dValue_dPhaseComposition, + arraySlice1d< real64 > const & dValue_dGlobalCompFraction, bool useMass ) const { GEOSX_UNUSED_VAR( pressure ); GEOSX_UNUSED_VAR( phaseComposition ); + GEOSX_UNUSED_VAR( dPhaseComposition_dPressure ); + GEOSX_UNUSED_VAR( dPhaseComposition_dTemperature ); + GEOSX_UNUSED_VAR( dPhaseComposition_dGlobalCompFraction ); + GEOSX_UNUSED_VAR( useMass ); value = m_coef0 + m_coef1 * temperature; dValue_dPressure = 0.0; dValue_dTemperature = m_coef1; - for( real64 & val : dValue_dPhaseComposition ) + for( real64 & val : dValue_dGlobalCompFraction ) { val = 0.0; } diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2Solubility.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2Solubility.hpp index b99bcf04197..578bbb6332f 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/CO2Solubility.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/CO2Solubility.hpp @@ -189,15 +189,15 @@ void CO2SolubilityUpdate::compute( real64 const & pressure, if( compFraction[m_CO2Index] > 1.0 - minForDivision ) { Y = compFraction[m_CO2Index] / minForDivision; - dY_dCompFrac[m_CO2Index] = (1.0 - compFraction[m_CO2Index]) / minForDivision; - dY_dCompFrac[m_waterIndex] = -compFraction[m_CO2Index] / minForDivision; + dY_dCompFrac[m_CO2Index] = 1.0 / minForDivision; + dY_dCompFrac[m_waterIndex] = 0.0; } else { real64 const oneMinusCompFracInv = 1.0 / (1.0 - compFraction[m_CO2Index]); Y = compFraction[m_CO2Index] * oneMinusCompFracInv; - dY_dCompFrac[m_CO2Index] = 1.0 * oneMinusCompFracInv; - dY_dCompFrac[m_waterIndex] = -compFraction[m_CO2Index] * oneMinusCompFracInv * oneMinusCompFracInv; + dY_dCompFrac[m_CO2Index] = oneMinusCompFracInv * oneMinusCompFracInv; + dY_dCompFrac[m_waterIndex] = 0.0; } if( Y < solubility ) @@ -231,8 +231,7 @@ void CO2SolubilityUpdate::compute( real64 const & pressure, phaseCompFraction[m_phaseGasIndex][m_waterIndex] = 0.0; for( localIndex jc = 0; jc < 2; ++jc ) { - dPhaseCompFraction_dCompFraction[m_phaseLiquidIndex][ic][jc] = - (ic == jc ) ? ( 1 - compFraction[ic] ) : -compFraction[ic]; + dPhaseCompFraction_dCompFraction[m_phaseLiquidIndex][ic][jc] = (ic == jc ) ? 1.0 : 0.0; dPhaseCompFraction_dCompFraction[m_phaseGasIndex][ic][jc] = 0.0; } } diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2Viscosity.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2Viscosity.hpp index 51910b75a62..0307d1fdc30 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2Viscosity.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/FenghourCO2Viscosity.hpp @@ -62,10 +62,13 @@ class FenghourCO2ViscosityUpdate final : public PVTFunctionBaseUpdate virtual void compute( real64 const & pressure, real64 const & temperature, arraySlice1d< real64 const > const & phaseComposition, + arraySlice1d< real64 const > const & dPhaseComposition_dPressure, + arraySlice1d< real64 const > const & dPhaseComposition_dTemperature, + arraySlice2d< real64 const > const & dPhaseComposition_dGlobalCompFraction, real64 & value, real64 & dValue_dPressure, real64 & dValue_dTemperature, - arraySlice1d< real64 > const & dValue_dPhaseComposition, + arraySlice1d< real64 > const & dValue_dGlobalCompFraction, bool useMass = 0 ) const override; protected: @@ -124,13 +127,19 @@ GEOSX_FORCE_INLINE void FenghourCO2ViscosityUpdate::compute( real64 const & pressure, real64 const & temperature, arraySlice1d< real64 const > const & phaseComposition, + arraySlice1d< real64 const > const & dPhaseComposition_dPressure, + arraySlice1d< real64 const > const & dPhaseComposition_dTemperature, + arraySlice2d< real64 const > const & dPhaseComposition_dGlobalCompFraction, real64 & value, real64 & dValue_dPressure, real64 & dValue_dTemperature, - arraySlice1d< real64 > const & dValue_dPhaseComposition, + arraySlice1d< real64 > const & dValue_dGlobalCompFraction, bool useMass ) const { GEOSX_UNUSED_VAR( phaseComposition ); + GEOSX_UNUSED_VAR( dPhaseComposition_dPressure ); + GEOSX_UNUSED_VAR( dPhaseComposition_dTemperature ); + GEOSX_UNUSED_VAR( dPhaseComposition_dGlobalCompFraction ); GEOSX_UNUSED_VAR( useMass ); real64 const input[2] = { pressure, temperature }; @@ -139,7 +148,7 @@ void FenghourCO2ViscosityUpdate::compute( real64 const & pressure, dValue_dPressure = densityDeriv[0]; dValue_dTemperature = densityDeriv[1]; - for( real64 & val : dValue_dPhaseComposition ) + for( real64 & val : dValue_dGlobalCompFraction ) { val = 0.0; } diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionBase.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionBase.hpp index c6b9bfa5670..98063907cee 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionBase.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/PVTFunctionBase.hpp @@ -62,10 +62,13 @@ class PVTFunctionBaseUpdate virtual void compute( real64 const & pressure, real64 const & temperature, arraySlice1d< real64 const > const & phaseComposition, + arraySlice1d< real64 const > const & dPhaseComposition_dPressure, + arraySlice1d< real64 const > const & dPhaseComposition_dTemperature, + arraySlice2d< real64 const > const & dPhaseComposition_dGlobalCompFraction, real64 & value, - real64 & dValue_dPresure, + real64 & dValue_dPressure, real64 & dValue_dTemperature, - arraySlice1d< real64 > const & dValue_dPhaseComposition, + arraySlice1d< real64 > const & dValue_dGlobalCompFraction, bool useMass = 0 ) const = 0; protected: diff --git a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2Density.hpp b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2Density.hpp index fb921ff8a8e..e9248e4f0f9 100644 --- a/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2Density.hpp +++ b/src/coreComponents/constitutive/fluid/PVTFunctions/SpanWagnerCO2Density.hpp @@ -64,10 +64,13 @@ class SpanWagnerCO2DensityUpdate final : public PVTFunctionBaseUpdate virtual void compute( real64 const & pressure, real64 const & temperature, arraySlice1d< real64 const > const & phaseComposition, + arraySlice1d< real64 const > const & dPhaseComposition_dPressure, + arraySlice1d< real64 const > const & dPhaseComposition_dTemperature, + arraySlice2d< real64 const > const & dPhaseComposition_dGlobalCompFraction, real64 & value, real64 & dValue_dPressure, real64 & dValue_dTemperature, - arraySlice1d< real64 > const & dValue_dPhaseComposition, + arraySlice1d< real64 > const & dValue_dGlobalCompFraction, bool useMass = 0 ) const override; protected: @@ -137,13 +140,19 @@ GEOSX_FORCE_INLINE void SpanWagnerCO2DensityUpdate::compute( real64 const & pressure, real64 const & temperature, arraySlice1d< real64 const > const & phaseComposition, + arraySlice1d< real64 const > const & dPhaseComposition_dPressure, + arraySlice1d< real64 const > const & dPhaseComposition_dTemperature, + arraySlice2d< real64 const > const & dPhaseComposition_dGlobalCompFraction, real64 & value, real64 & dValue_dPressure, real64 & dValue_dTemperature, - arraySlice1d< real64 > const & dValue_dPhaseComposition, + arraySlice1d< real64 > const & dValue_dGlobalCompFraction, bool useMass ) const { GEOSX_UNUSED_VAR( phaseComposition ); + GEOSX_UNUSED_VAR( dPhaseComposition_dPressure ); + GEOSX_UNUSED_VAR( dPhaseComposition_dTemperature ); + GEOSX_UNUSED_VAR( dPhaseComposition_dGlobalCompFraction ); real64 const input[2] = { pressure, temperature }; real64 densityDeriv[2]{}; @@ -158,7 +167,7 @@ void SpanWagnerCO2DensityUpdate::compute( real64 const & pressure, dValue_dTemperature /= m_componentMolarWeight[m_CO2Index]; } - for( real64 & val : dValue_dPhaseComposition ) + for( real64 & val : dValue_dGlobalCompFraction ) { val = 0.0; } diff --git a/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp b/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp index 1e3077ba481..c5bf46ab2df 100644 --- a/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp +++ b/src/coreComponents/constitutive/unitTests/testCO2BrinePVTModels.cpp @@ -56,14 +56,20 @@ void testValuesAgainstPreviousImplementation( PVTFunctionBaseUpdate const & pvtF real64 value = 0.0; real64 dValue_dPressure = 0.0; real64 dValue_dTemperature = 0.0; - stackArray1d< real64, 2 > dValue_dPhaseComposition( 2 ); + stackArray1d< real64, 2 > dPhaseComposition_dPressure( 2 ); + stackArray1d< real64, 2 > dPhaseComposition_dTemperature( 2 ); + stackArray2d< real64, 4 > dPhaseComposition_dGlobalCompFraction( 2, 2 ); + stackArray1d< real64, 2 > dValue_dGlobalCompFraction( 2 ); pvtFunctionWrapper.compute( pressure, temperature, phaseComposition, + dPhaseComposition_dPressure, + dPhaseComposition_dTemperature, + dPhaseComposition_dGlobalCompFraction, value, dValue_dPressure, dValue_dTemperature, - dValue_dPhaseComposition, + dValue_dGlobalCompFraction, useMass ); checkRelativeError( value, oldImplValue, relTol ); @@ -130,29 +136,40 @@ void testNumericalDerivatives( PVTFunctionBaseUpdate const & pvtFunctionWrapper, real64 value = 0.0; real64 dValue_dPressure = 0.0; real64 dValue_dTemperature = 0.0; - stackArray1d< real64, 2 > dValue_dPhaseComposition( 2 ); + stackArray1d< real64, 2 > dPhaseComposition_dPressure( 2 ); + stackArray1d< real64, 2 > dPhaseComposition_dTemperature( 2 ); + stackArray2d< real64, 4 > dPhaseComposition_dGlobalCompFraction( 2, 2 ); + stackArray1d< real64, 2 > dValue_dGlobalCompFraction( 2 ); + dPhaseComposition_dGlobalCompFraction[0][0] = 1.0; + dPhaseComposition_dGlobalCompFraction[1][1] = 1.0; pvtFunctionWrapper.compute( pressure, temperature, phaseComposition, + dPhaseComposition_dPressure, + dPhaseComposition_dTemperature, + dPhaseComposition_dGlobalCompFraction, value, dValue_dPressure, dValue_dTemperature, - dValue_dPhaseComposition, + dValue_dGlobalCompFraction, useMass ); real64 perturbedValue = 0.0; real64 dPerturbedValue_dPressure = 0.0; real64 dPerturbedValue_dTemperature = 0.0; - stackArray1d< real64, 2 > dPerturbedValue_dPhaseComposition( 2 ); + stackArray1d< real64, 2 > dPerturbedValue_dGlobalCompFraction( 2 ); // 2) Check derivative with respect to pressure real64 const dP = perturbParameter * (pressure + perturbParameter); pvtFunctionWrapper.compute( pressure + dP, temperature, phaseComposition, + dPhaseComposition_dPressure, + dPhaseComposition_dTemperature, + dPhaseComposition_dGlobalCompFraction, perturbedValue, dPerturbedValue_dPressure, dPerturbedValue_dTemperature, - dPerturbedValue_dPhaseComposition, + dPerturbedValue_dGlobalCompFraction, useMass ); checkRelativeError( (perturbedValue-value)/dP, dValue_dPressure, relTol ); @@ -161,10 +178,13 @@ void testNumericalDerivatives( PVTFunctionBaseUpdate const & pvtFunctionWrapper, pvtFunctionWrapper.compute( pressure, temperature + dT, phaseComposition, + dPhaseComposition_dPressure, + dPhaseComposition_dTemperature, + dPhaseComposition_dGlobalCompFraction, perturbedValue, dPerturbedValue_dPressure, dPerturbedValue_dTemperature, - dPerturbedValue_dPhaseComposition, + dPerturbedValue_dGlobalCompFraction, useMass ); checkRelativeError( (perturbedValue-value)/dT, dValue_dTemperature, relTol ); @@ -176,17 +196,19 @@ void testNumericalDerivatives( PVTFunctionBaseUpdate const & pvtFunctionWrapper, for( localIndex j = 0; j < 2; ++j ) { perturbedPhaseComposition[j] = phaseComposition[j] + ( (i == j) ? dC : 0.0 ); - perturbedPhaseComposition[j] /= ( 1 + dC ); } pvtFunctionWrapper.compute( pressure, temperature, perturbedPhaseComposition, + dPhaseComposition_dPressure, + dPhaseComposition_dTemperature, + dPhaseComposition_dGlobalCompFraction, perturbedValue, dPerturbedValue_dPressure, dPerturbedValue_dTemperature, - dPerturbedValue_dPhaseComposition, + dPerturbedValue_dGlobalCompFraction, useMass ); - checkRelativeError( (perturbedValue-value)/dC, dValue_dPhaseComposition[i], relTol ); + checkRelativeError( (perturbedValue-value)/dC, dValue_dGlobalCompFraction[i], relTol ); } } @@ -278,7 +300,6 @@ void testNumericalDerivatives( FlashModelBaseUpdate const & flashModelWrapper, for( localIndex j = 0; j < 2; ++j ) { perturbedCompFraction[j] = compFraction[j] + ( (i == j) ? dC : 0.0 ); - perturbedCompFraction[j] /= ( 1 + dC ); } flashModelWrapper.compute( pressure, temperature, @@ -590,14 +611,6 @@ TEST_F( BrineCO2DensityTest, brineCO2DensityMolarValuesAndDeriv ) real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); real64 const relTol = 5e-5; - // ======================================================================= - // TODO FRANCOIS: NEW AND OLD MODEL PRODUCE NEGATIVE MOLAR DENSITIES !!!! - // ======================================================================= - real64 const savedValues[] = { 32023.1563, 31987.53048, 31957.40422, 31997.76967, 31962.01198, 31931.77369, 31943.80393, - 31907.76711, 31877.29169, 3267.434571, 3221.843011, 3182.926776, 3071.375934, 3025.161549, 2985.719723, - 2660.391855, 2612.877907, 2572.339248, -64347.37057, -64416.39509, -64475.97965, -64944.73907, - -65015.54082, -65076.62339, -66195.19869, -66269.69941, -66333.90028 }; - BrineCO2Density::KernelWrapper pvtFunctionWrapper = pvtFunction->createKernelWrapper(); localIndex counter = 0; @@ -607,8 +620,8 @@ TEST_F( BrineCO2DensityTest, brineCO2DensityMolarValuesAndDeriv ) { for( localIndex iTemp = 0; iTemp < 3; ++iTemp ) { - testValuesAgainstPreviousImplementation( pvtFunctionWrapper, - P[iPres], TC[iTemp], comp, savedValues[counter], false, relTol ); + //testValuesAgainstPreviousImplementation( pvtFunctionWrapper, + // P[iPres], TC[iTemp], comp, savedValues[counter], false, relTol ); testNumericalDerivatives( pvtFunctionWrapper, P[iPres], TC[iTemp], comp, false, eps, relTol ); counter++; } diff --git a/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp b/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp index 3f10b6215b3..74f8576830b 100644 --- a/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp +++ b/src/coreComponents/constitutive/unitTests/testMultiFluid.cpp @@ -126,6 +126,7 @@ void testNumericalDerivatives( MultiFluidBase & fluid, real64 const T, arraySlice1d< real64 > const & composition, real64 const perturbParameter, + bool usePVTPackage, real64 const relTol, real64 const absTol = std::numeric_limits< real64 >::max() ) { @@ -260,12 +261,24 @@ void testNumericalDerivatives( MultiFluidBase & fluid, } compNew[jc] += dC; - // renormalize - real64 sum = 0.0; - for( localIndex ic = 0; ic < NC; ++ic ) - sum += compNew[ic]; - for( localIndex ic = 0; ic < NC; ++ic ) - compNew[ic] /= sum; + // Note: in PVTPackage, derivatives are obtained with finite-difference approx + // The component fraction is perturbed (just as above), and then all the component fractions are normalized (as below) + // But, in the native DO model and in CO2Brine, derivatives are computed analytically. Say, in the 2-phase DO, that you want + // to compute the derivatives of phase fraction wrt component fraction. Analytically we have + // dPhaseFraction_dGlobalFraction[ic][jc] = (ic == jc) + // which is correct but will fail the test below. Instead, the finite-difference approx a la PVTPackage yields + // dPhaseFraction_dGlobalFraction[ic][jc] = (ic == jc) ? 1-composition[ic] : -composition[ic] + // because of the normalization. The second option is, in my opinion, not correct, unless I missed some + // cancellations that happen after when we differentiate wrt component densities. Hence the flag below. + if( usePVTPackage ) + { + // renormalize + real64 sum = 0.0; + for( localIndex ic = 0; ic < NC; ++ic ) + sum += compNew[ic]; + for( localIndex ic = 0; ic < NC; ++ic ) + compNew[ic] /= sum; + } fluidWrapper.update( 0, 0, P, T, compNew ); @@ -452,7 +465,7 @@ TEST_F( CompositionalFluidTest, numericalDerivativesMolar ) real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); real64 const relTol = 1e-4; - testNumericalDerivatives( *fluid, parent, P, T, comp, eps, relTol ); + testNumericalDerivatives( *fluid, parent, P, T, comp, eps, true, relTol ); } TEST_F( CompositionalFluidTest, numericalDerivativesMass ) @@ -468,7 +481,7 @@ TEST_F( CompositionalFluidTest, numericalDerivativesMass ) real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); real64 const relTol = 1e-2; - testNumericalDerivatives( *fluid, parent, P, T, comp, eps, relTol ); + testNumericalDerivatives( *fluid, parent, P, T, comp, eps, true, relTol ); } MultiFluidBase & makeLiveOilFluid( string const & name, Group * parent ) @@ -687,7 +700,7 @@ TEST_F( LiveOilFluidTest, numericalDerivativesMolar ) real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); real64 const relTol = 1e-4; - testNumericalDerivatives( *fluid, parent, P, T, comp, eps, relTol ); + testNumericalDerivatives( *fluid, parent, P, T, comp, eps, true, relTol ); } TEST_F( LiveOilFluidTest, numericalDerivativesMass ) @@ -704,7 +717,7 @@ TEST_F( LiveOilFluidTest, numericalDerivativesMass ) real64 const relTol = 1e-2; real64 const absTol = 1e-14; - testNumericalDerivatives( *fluid, parent, P, T, comp, eps, relTol, absTol ); + testNumericalDerivatives( *fluid, parent, P, T, comp, eps, true, relTol, absTol ); } class DeadOilFluidTest : public CompositionalFluidTestBase @@ -746,7 +759,7 @@ TEST_F( DeadOilFluidTest, numericalDerivativesMolar ) for( localIndex i = 0; i < 3; ++i ) { - testNumericalDerivatives( *fluid, parent, P[i], T, comp, eps, relTol ); + testNumericalDerivatives( *fluid, parent, P[i], T, comp, eps, false, relTol ); } } @@ -765,7 +778,7 @@ TEST_F( DeadOilFluidTest, numericalDerivativesMass ) for( localIndex i = 0; i < 3; ++i ) { - testNumericalDerivatives( *fluid, parent, P[i], T, comp, eps, relTol, absTol ); + testNumericalDerivatives( *fluid, parent, P[i], T, comp, eps, false, relTol, absTol ); } } @@ -797,7 +810,7 @@ TEST_F( DeadOilFluidFromTableTest, numericalDerivativesMolar ) for( localIndex i = 0; i < 3; ++i ) { - testNumericalDerivatives( *fluid, parent, P[i], T, comp, eps, relTol ); + testNumericalDerivatives( *fluid, parent, P[i], T, comp, eps, false, relTol ); } } @@ -1002,7 +1015,7 @@ TEST_F( MultiPhaseMultiComponentFluidTest, numericalDerivativesMolar ) { for( localIndex j = 0; j < 3; ++j ) { - testNumericalDerivatives( *fluid, parent, P[i], T[j], comp, eps, relTol ); + testNumericalDerivatives( *fluid, parent, P[i], T[j], comp, eps, false, relTol ); } } } @@ -1018,13 +1031,13 @@ TEST_F( MultiPhaseMultiComponentFluidTest, numericalDerivativesMass ) comp[0] = 0.3; comp[1] = 0.7; real64 const eps = sqrt( std::numeric_limits< real64 >::epsilon()); - real64 const relTol = 1e-4; + real64 const relTol = 1e-8; for( localIndex i = 0; i < 3; ++i ) { for( localIndex j = 0; j < 3; ++j ) { - testNumericalDerivatives( *fluid, parent, P[i], T[j], comp, eps, relTol ); + testNumericalDerivatives( *fluid, parent, P[i], T[j], comp, eps, false, relTol ); } } } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/integratedTests/compositionalMultiphaseFlow/co2_hybrid_1d.xml b/src/coreComponents/physicsSolvers/fluidFlow/integratedTests/compositionalMultiphaseFlow/co2_hybrid_1d.xml index 68644c5364a..f7046f6820f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/integratedTests/compositionalMultiphaseFlow/co2_hybrid_1d.xml +++ b/src/coreComponents/physicsSolvers/fluidFlow/integratedTests/compositionalMultiphaseFlow/co2_hybrid_1d.xml @@ -191,7 +191,7 @@ name="sourceTerm" objectPath="ElementRegions/region/cb" fieldName="pressure" - scale="5e7" + scale="1.45e7" setNames="{ source }"/> diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/integratedTests/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml b/src/coreComponents/physicsSolvers/fluidFlow/wells/integratedTests/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml index bd0ade62f02..d283ba192ba 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/integratedTests/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/integratedTests/compositionalMultiphaseWell/staircase_co2_wells_hybrid_3d.xml @@ -55,8 +55,8 @@ type="injector" control="totalVolRate" referenceElevation="12" - targetBHP="5e7" - targetTotalRate="7.5e-6" + targetBHP="1.45e7" + targetTotalRate="7.5e-7" injectionStream="{ 0.995, 0.005 }"/>