Raw File
/**
 * \copyright
 * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
 *            Distributed under a Modified BSD License.
 *              See accompanying file LICENSE.txt or
 *              http://www.opengeosys.org/project/license
 *
 * \file
 *
 * Created on November 2, 2016, 3:09 PM
 */

#include <gtest/gtest.h>

#include <memory>
#include <vector>

#include "BaseLib/ConfigTree.h"
#include "MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/CreateRelativePermeabilityModel.h"
#include "MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/RelativePermeability.h"
#include "Tests/TestTools.h"

using namespace MaterialLib;
using namespace MaterialLib::PorousMedium;

std::unique_ptr<RelativePermeability> createRelativePermeabilityModel(
    const char xml[])
{
    auto ptree = Tests::readXml(xml);
    BaseLib::ConfigTree conf(std::move(ptree), "", BaseLib::ConfigTree::onerror,
                             BaseLib::ConfigTree::onwarning);
    auto const& sub_config = conf.getConfigSubtree("relative_permeability");
    sub_config.ignoreConfigAttribute("id");
    return createRelativePermeabilityModel(sub_config);
}

TEST(MaterialPorousMedium, checkWettingPhaseVanGenuchten)
{
    const char xml[] =
        "<relative_permeability id=\"0\">"
        "   <type>WettingPhaseVanGenuchten</type>"
        "   <sr>  0.2772 </sr> "
        "   <smax> 1. </smax> "
        "   <m> 0.5 </m> "
        "   <krel_min> 1.e-9 </krel_min> "
        "</relative_permeability>";
    auto const perm_model = createRelativePermeabilityModel(xml);

    std::vector<double> S = {0.2, 0.33, 0.45, 0.52, 0.6, 0.85};
    std::vector<double> krel = {1.e-9,
                                1.9291770102827742e-006,
                                0.00041114113180510661,
                                0.0019569840357319015,
                                0.0074049488610241927,
                                0.13546615958442240};

    const double perturbation = 1.e-9;
    for (std::size_t i = 0; i < S.size(); i++)
    {
        ASSERT_NEAR(krel[i], perm_model->getValue(S[i]), 1.e-9);

        // Compare the derivative with numerical one.
        ASSERT_NEAR((perm_model->getValue(S[i] + perturbation) -
                     perm_model->getValue(S[i])) /
                        perturbation,
                    perm_model->getdValue(S[i]), 1.e-6);
    }
}

TEST(MaterialPorousMedium, checkNonWettingPhaseVanGenuchten)
{
    const char xml[] =
        "<relative_permeability id=\"0\">"
        "   <type>NonWettingPhaseVanGenuchten</type>"
        "   <sr>  0.1 </sr> "
        "   <smax> 1. </smax> "
        "   <m> 0.5 </m> "
        "   <krel_min> 1.e-9 </krel_min> "
        "</relative_permeability>";
    auto const perm_model = createRelativePermeabilityModel(xml);

    std::vector<double> S = {0.2, 0.33, 0.45, 0.52, 0.6, 0.85};
    std::vector<double> krel = {0.87422700239237161, 0.74331414436457388,
                                0.59527539448807487, 0.49976666464188485,
                                0.38520070797257489, 0.041219134248319585};

    const double perturbation = 1.e-9;
    for (std::size_t i = 0; i < S.size(); i++)
    {
        ASSERT_NEAR(krel[i], perm_model->getValue(S[i]), 1.e-9);

        // Compare the derivative with numerical one.
        ASSERT_NEAR((perm_model->getValue(S[i] + perturbation) -
                     perm_model->getValue(S[i])) /
                        perturbation,
                    perm_model->getdValue(S[i]), 1.e-6);
    }
}

TEST(MaterialPorousMedium, checkWettingPhaseBrooksCoreyOilGas)
{
    const char xml[] =
        "<relative_permeability id=\"0\">"
        "   <type>WettingPhaseBrooksCoreyOilGas</type>"
        "   <sr>  0.2 </sr> "
        "   <smax> 0.8 </smax> "
        "   <m> 2 </m> "
        "   <krel_min> 1.e-9 </krel_min> "
        "</relative_permeability>";
    auto const perm_model = createRelativePermeabilityModel(xml);

    std::vector<double> S = {0.2, 0.33, 0.45, 0.52, 0.6, 0.85};
    std::vector<double> krel = {0.,
                                0.0022037808641975302,
                                0.030140817901234556,
                                0.080908641975308573,
                                0.19753086419753069,
                                1.0};

    const double perturbation = 1.e-9;
    for (std::size_t i = 0; i < S.size(); i++)
    {
        ASSERT_NEAR(krel[i], perm_model->getValue(S[i]), 1.e-9);

        // i ==  S.size() -1, S(=0.85) is limited to 0.8, and the numerical
        // derivative of krel is unavailable.
        if (i == S.size() - 1)
        {
            continue;
        }
        // Compare the derivative with numerical one.
        ASSERT_NEAR((perm_model->getValue(S[i] + perturbation) -
                     perm_model->getValue(S[i])) /
                        perturbation,
                    perm_model->getdValue(S[i]), 1.e-6);
    }
}

TEST(MaterialPorousMedium, checkNonWettingPhaseBrooksCoreyOilGas)
{
    const char xml[] =
        "<relative_permeability id=\"0\">"
        "   <type>NonWettingPhaseBrooksCoreyOilGas</type>"
        "   <sr>  0.2 </sr> "
        "   <smax> 0.8 </smax> "
        "   <m> 2 </m> "
        "   <krel_min> 1.e-9 </krel_min> "
        "</relative_permeability>";
    auto const perm_model = createRelativePermeabilityModel(xml);

    std::vector<double> S = {0.2, 0.33, 0.45, 0.52, 0.6, 0.85};
    std::vector<double> krel = {1.0,
                                0.58480547839506147,
                                0.28120177469135793,
                                0.15583209876543211,
                                0.061728395061728412,
                                .0};

    const double perturbation = 1.e-9;
    for (std::size_t i = 0; i < S.size(); i++)
    {
        ASSERT_NEAR(krel[i], perm_model->getValue(S[i]), 1.e-9);

        // Compare the derivative with numerical one.
        ASSERT_NEAR((perm_model->getValue(S[i] + perturbation) -
                     perm_model->getValue(S[i])) /
                        perturbation,
                    perm_model->getdValue(S[i]), 1.e-6);
    }
}

TEST(MaterialPorousMedium, checkReletivePermeabilityCurve)
{
    const char xml[] =
        "<relative_permeability id=\"0\">"
        "   <type>Curve</type>"
        "       <curve>"
        "           <coords> 0.   0.4 0.9  </coords>"
        "           <values> 0.9  0.5 0.01 </values>"
        "       </curve>"
        "</relative_permeability>";
    auto const perm_model = createRelativePermeabilityModel(xml);

    std::vector<double> S = {0.2, 0.33, 0.45, 0.52, 0.6, 0.85};
    std::vector<double> krel = {0.7, 0.57, 0.451, 0.3824, 0.304, 0.059};

    const double perturbation = 1.e-9;
    for (std::size_t i = 0; i < S.size(); i++)
    {
        ASSERT_NEAR(krel[i], perm_model->getValue(S[i]), 1.e-9);

        // Compare the derivative with numerical one.
        ASSERT_NEAR((perm_model->getValue(S[i] + perturbation) -
                     perm_model->getValue(S[i])) /
                        perturbation,
                    perm_model->getdValue(S[i]), 1.e-6);
    }
}
back to top