Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New MPL property: Brooks&Corey relative permeability #2656

Merged
@@ -0,0 +1 @@
The relative permeability function proposed by Brooks&Corey (1964) \cite BrooksCorey1964.
@@ -0,0 +1 @@
The minimal relative permeability of the gas (or non-wetting) phase.
@@ -0,0 +1 @@
The minimal relative permeability of the liquid (or wetting) phase.
@@ -0,0 +1 @@
Exponent of the Brooks&Corey relative permeability function.
@@ -0,0 +1 @@
The smallest degree of saturation of the gas (or non-wetting) phase in the medium.
@@ -0,0 +1 @@
The smallest degree of saturation of the liquid (or wetting) phase in the medium.
5 changes: 5 additions & 0 deletions MaterialLib/MPL/CreateProperty.cpp
Expand Up @@ -65,6 +65,11 @@ std::unique_ptr<MaterialPropertyLib::Property> createProperty(
return createSaturationBrooksCorey(config);
}

if (boost::iequals(property_type, "RelPermBrooksCorey"))
{
return createRelPermBrooksCorey(config);
}

// If none of the above property types are found, OGS throws an error.
OGS_FATAL("The specified component property type '%s' was not recognized",
property_type.c_str());
Expand Down
1 change: 1 addition & 0 deletions MaterialLib/MPL/Properties/CreateProperties.h
Expand Up @@ -17,4 +17,5 @@
#include "CreateIdealGasLaw.h"
#include "CreateLinearProperty.h"
#include "CreateParameterProperty.h"
#include "CreateRelPermBrooksCorey.h"
#include "CreateSaturationBrooksCorey.h"
50 changes: 50 additions & 0 deletions MaterialLib/MPL/Properties/CreateRelPermBrooksCorey.cpp
@@ -0,0 +1,50 @@
/**
* \copyright
endJunction marked this conversation as resolved.
Show resolved Hide resolved
* Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/

#include "BaseLib/ConfigTree.h"
#include "RelPermBrooksCorey.h"

namespace MaterialPropertyLib
{
std::unique_ptr<RelPermBrooksCorey> createRelPermBrooksCorey(
BaseLib::ConfigTree const& config)
{
// check is reading the parameter, not peeking it...
//! \ogs_file_param{prj__media__medium__properties__property__RelPermBrooksCorey}
config.checkConfigParameter("type", "RelPermBrooksCorey");
DBUG("Create RelPermBrooksCorey medium property");

auto const residual_liquid_saturation =
//! \ogs_file_param{prj__media__medium__properties__property__RelPermBrooksCorey__residual_liquid_saturation}
config.getConfigParameter<double>("residual_liquid_saturation");
auto const residual_gas_saturation =
//! \ogs_file_param{prj__media__medium__properties__property__RelPermBrooksCorey__residual_gas_saturation}
config.getConfigParameter<double>("residual_gas_saturation");
auto const min_relative_permeability_liquid =
//! \ogs_file_param{prj__media__medium__properties__property__RelPermBrooksCorey__k_rel_min_liquid}
config.getConfigParameter<double>("min_relative_permeability_liquid");
auto const min_relative_permeability_gas =
//! \ogs_file_param{prj__media__medium__properties__property__RelPermBrooksCorey__k_rel_min_gas}
config.getConfigParameter<double>("min_relative_permeability_gas");
auto const exponent =
//! \ogs_file_param{prj__media__medium__properties__property__RelPermBrooksCorey__lambda}
config.getConfigParameter<double>("lambda");
if (exponent == 0.)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message below is different from the check.

Suggested change
if (exponent == 0.)
if (exponent <= 0.)

{
OGS_FATAL("Exponent 'lambda' must be positive.");
}

return std::make_unique<RelPermBrooksCorey>(
residual_liquid_saturation,
residual_gas_saturation,
min_relative_permeability_liquid,
min_relative_permeability_gas,
exponent);
}
} // namespace MaterialPropertyLib
26 changes: 26 additions & 0 deletions MaterialLib/MPL/Properties/CreateRelPermBrooksCorey.h
@@ -0,0 +1,26 @@
/**
* \copyright
endJunction marked this conversation as resolved.
Show resolved Hide resolved
* Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/

#pragma once

namespace BaseLib
{
class ConfigTree;
}

namespace MaterialPropertyLib
{
class RelPermBrooksCorey;
}

namespace MaterialPropertyLib
{
std::unique_ptr<RelPermBrooksCorey> createRelPermBrooksCorey(
BaseLib::ConfigTree const& config);
} // namespace MaterialPropertyLib
1 change: 1 addition & 0 deletions MaterialLib/MPL/Properties/Properties.h
Expand Up @@ -17,4 +17,5 @@
#include "IdealGasLaw.h"
#include "LinearProperty.h"
#include "ParameterProperty.h"
#include "RelPermBrooksCorey.h"
#include "SaturationBrooksCorey.h"
111 changes: 111 additions & 0 deletions MaterialLib/MPL/Properties/RelPermBrooksCorey.cpp
@@ -0,0 +1,111 @@
/**
* \author Norbert Grunwald
* \date 02.07.2018
* \brief
*
* \copyright
* Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/

#include "MaterialLib/MPL/Properties/RelPermBrooksCorey.h"
#include "MaterialLib/MPL/Medium.h"

#include <algorithm>
#include <cmath>

namespace MaterialPropertyLib
{
RelPermBrooksCorey::RelPermBrooksCorey(
const double residual_liquid_saturation,
const double residual_gas_saturation,
const double min_relative_permeability_liquid,
const double min_relative_permeability_gas,
const double exponent)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The empty line not necessary.

: _residual_liquid_saturation(residual_liquid_saturation),
_residual_gas_saturation(residual_gas_saturation),
_min_relative_permeability_liquid(min_relative_permeability_liquid),
_min_relative_permeability_gas(min_relative_permeability_gas),
_exponent(exponent){};

PropertyDataType RelPermBrooksCorey::value(
VariableArray const& variable_array,
ParameterLib::SpatialPosition const& pos,
double const t) const
{
/// here, an extra computation of saturation is forced, guaranteeing a
/// correct value. In order to speed up the computing time, saturation could
/// be insertred into the primary variable array after it is computed in the
/// FEM assembly.
auto const s_L = _medium->property(PropertyType::saturation)
.template value<double>(variable_array, pos, t);

auto const s_L_res = _residual_liquid_saturation;
auto const s_L_max = 1. - _residual_gas_saturation;
auto const k_rel_min_LR = _min_relative_permeability_liquid;
auto const k_rel_min_GR = _min_relative_permeability_gas;

auto const lambda = _exponent;

auto const s_eff = (s_L - s_L_res) / (s_L_max - s_L_res);

if (s_eff >= 1.0)
{
// fully saturated medium
return Pair{{1.0, k_rel_min_GR}};
}
if (s_eff <= 0.0)
{
// dry medium
return Pair{{k_rel_min_LR, 1.0}};
}

auto const k_rel_LR = std::pow(s_eff, (2. + 3. * lambda) / lambda);
auto const k_rel_GR = (1. - s_eff) * (1. - s_eff) *
(1. - std::pow(s_eff, (2. + lambda) / lambda));

const Pair kRel = {std::max(k_rel_LR, k_rel_min_LR),
std::max(k_rel_GR, k_rel_min_GR)};
return kRel;
}
PropertyDataType RelPermBrooksCorey::dValue(
VariableArray const& variable_array, Variable const primary_variable,
ParameterLib::SpatialPosition const& pos, double const t) const
{
(void)primary_variable;
assert((primary_variable == Variable::liquid_saturation) &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it is better to check this also in the release version?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure here, let's measure it!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talked with @Scinopode : The primary variable isn't user input. It is 'hard' coded in the process and mistakes should be detected while the development of a new process.

"RelPermBrooksCorey::dValue is implemented for "
" derivatives with respect to liquid saturation only.");
auto const s_L = _medium->property(PropertyType::saturation)
.template value<double>(variable_array, pos, t);

auto const s_L_res = _residual_liquid_saturation;
auto const s_L_max = 1. - _residual_gas_saturation;
auto const lambda = _exponent;

auto const s_eff = (s_L - s_L_res) / (s_L_max - s_L_res);
if ((s_eff < 0.) || (s_eff > 1.))
return Pair{0., 0.};

auto const d_se_d_sL = 1. / (s_L_max - s_L_res);
auto const dk_rel_LRdse =
(3 * lambda + 2.) / lambda * std::pow(s_eff, 2. / lambda + 2.);

auto const dk_rel_LRdsL = dk_rel_LRdse * d_se_d_sL;

auto const _2L_L = (2. + lambda) / lambda;
auto const dk_rel_GRdse =
-2. * (1 - s_eff) * (1. - std::pow(s_eff, _2L_L)) -
_2L_L * std::pow(s_eff, _2L_L - 1.) * (1. - s_eff) * (1. - s_eff);

auto const dk_rel_GRdsL = dk_rel_GRdse * d_se_d_sL;
const Pair dkReldsL = {{dk_rel_LRdsL, dk_rel_GRdsL}};

return dkReldsL;
}

} // namespace MaterialPropertyLib
75 changes: 75 additions & 0 deletions MaterialLib/MPL/Properties/RelPermBrooksCorey.h
@@ -0,0 +1,75 @@
/**
* \author Norbert Grunwald
* \date 27.06.2018
* \brief
*
* \copyright
* Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#pragma once

#include "BaseLib/ConfigTree.h"
#include "MaterialLib/MPL/Property.h"

namespace MaterialPropertyLib
{
class Medium;
class Phase;
class Component;
/**
* \class RelPermBrooksCorey
* \brief Relative permeability function proposed by Brooks&Corey
* \details This property must be a medium property, it
* computes the permeability reduction due to saturation as function
* of capillary pressure.
*/
class RelPermBrooksCorey final : public Property
{
private:
Medium* _medium;
const double _residual_liquid_saturation;
const double _residual_gas_saturation;
const double _min_relative_permeability_liquid;
const double _min_relative_permeability_gas;
const double _exponent;

public:
RelPermBrooksCorey(const double /*residual_liquid_saturation*/,
const double /*residual_gas_saturation*/,
const double /*_min_relative_permeability_liquid*/,
const double /*_min_relative_permeability_gas*/,
const double /*exponent*/
);
/// This method assigns a pointer to the meterial object that is the owner
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// This method assigns a pointer to the meterial object that is the owner
/// This method assigns a pointer to the material object that is the owner

/// of this property
void setScale(
std::variant<Medium*, Phase*, Component*> scale_pointer) override
{
if (std::holds_alternative<Medium*>(scale_pointer))
{
_medium = std::get<Medium*>(scale_pointer);
}
else
{
OGS_FATAL(
"The property 'RelPermBrooksCorey' is implemented on the "
"'media' scale only.");
}
}

/// Those methods override the base class implementations and
/// actually compute and set the property _values and _dValues.
PropertyDataType value(VariableArray const& variable_array,
ParameterLib::SpatialPosition const& pos,
double const t) const override;
PropertyDataType dValue(VariableArray const& variable_array,
Variable const variable,
ParameterLib::SpatialPosition const& pos,
double const t) const override;
};

} // namespace MaterialPropertyLib