Skip to content

Commit

Permalink
Merge pull request #2656 from Scinopode/mpl_brooks_corey_relative_per…
Browse files Browse the repository at this point in the history
…meability

New MPL property: Brooks&Corey relative permeability
  • Loading branch information
TomFischer authored Sep 12, 2019
2 parents ce1dbf0 + dce8c96 commit 5b00fe3
Show file tree
Hide file tree
Showing 14 changed files with 403 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The relative permeability function proposed by Brooks&Corey (1964) \cite BrooksCorey1964.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The minimal relative permeability of the gas (or non-wetting) phase.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The minimal relative permeability of the liquid (or wetting) phase.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Exponent of the Brooks&Corey relative permeability function.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The smallest degree of saturation of the gas (or non-wetting) phase in the medium.
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@
#include "CreateIdealGasLaw.h"
#include "CreateLinearProperty.h"
#include "CreateParameterProperty.h"
#include "CreateRelPermBrooksCorey.h"
#include "CreateSaturationBrooksCorey.h"
51 changes: 51 additions & 0 deletions MaterialLib/MPL/Properties/CreateRelPermBrooksCorey.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* \file
* \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
*
*/

#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.)
{
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
27 changes: 27 additions & 0 deletions MaterialLib/MPL/Properties/CreateRelPermBrooksCorey.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* \file
* \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

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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/**
* \file
* \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)
: _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) &&
"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
76 changes: 76 additions & 0 deletions MaterialLib/MPL/Properties/RelPermBrooksCorey.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* \file
* \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 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
Loading

0 comments on commit 5b00fe3

Please sign in to comment.