Skip to content
Snippets Groups Projects
Forked from ogs / ogs
1640 commits behind the upstream repository.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
TestLinearElasticTransverseIsotropic.cpp 11.77 KiB
/**
 * \file
 * \copyright
 * Copyright (c) 2012-2024, OpenGeoSys Community (http://www.opengeosys.org)
 *            Distributed under a Modified BSD License.
 *              See accompanying file LICENSE.txt or
 *              http://www.opengeosys.org/project/license
 *
 * Created on November 7, 2023, 10:39 AM
 */

#include <gtest/gtest.h>

#include <cmath>
#include <memory>
#include <string>

#include "CreateTestConstitutiveRelation.h"
#include "MaterialLib/SolidModels/CreateLinearElasticIsotropic.h"
#include "MaterialLib/SolidModels/CreateLinearElasticOrthotropic.h"
#include "MaterialLib/SolidModels/CreateLinearElasticTransverseIsotropic.h"
#include "MathLib/KelvinVector.h"
#include "ParameterLib/ConstantParameter.h"
#include "ParameterLib/CoordinateSystem.h"

constexpr char xml_ti[] =
    "<constitutive_relation> "
    "    <type>LinearElasticTransverseIsotropic</type>"
    "    <youngs_modulus_i>E_i</youngs_modulus_i>"
    "    <youngs_modulus_a>E_a</youngs_modulus_a>"
    "    <poissons_ratio_ii>nu_i</poissons_ratio_ii>"
    "    <poissons_ratio_ia>nu_ia</poissons_ratio_ia>"
    "    <shear_modulus_ia>G_a</shear_modulus_ia>"
    "</constitutive_relation> ";

constexpr char xml_orth[] =
    "<constitutive_relation> "
    "    <type>LinearElasticOrthotropic</type>"
    "    <youngs_moduli>E0</youngs_moduli>"
    "    <shear_moduli>G0</shear_moduli>"
    "    <poissons_ratios>nu0</poissons_ratios>"
    "</constitutive_relation> ";

constexpr char xml_iso[] =
    "<constitutive_relation> "
    "    <type>LinearElasticIsotropic</type>"
    "    <youngs_modulus>E</youngs_modulus>"
    "    <poissons_ratio>nu</poissons_ratio>"
    "</constitutive_relation> ";

std::vector<std::unique_ptr<ParameterLib::ParameterBase>>
setParametersForLinearElasticTransverseIsotropic(double const E_i,
                                                 double const E_a,
                                                 double const nu_i,
                                                 double const nu_ia,
                                                 double const G_a)
{
    std::vector<std::unique_ptr<ParameterLib::ParameterBase>> parameters;
    parameters.push_back(
        std::make_unique<ParameterLib::ConstantParameter<double>>("E_i", E_i));
    parameters.push_back(
        std::make_unique<ParameterLib::ConstantParameter<double>>("E_a", E_a));
    parameters.push_back(
        std::make_unique<ParameterLib::ConstantParameter<double>>("nu_i",
                                                                  nu_i));
    parameters.push_back(
        std::make_unique<ParameterLib::ConstantParameter<double>>("nu_ia",
                                                                  nu_ia));
    parameters.push_back(
        std::make_unique<ParameterLib::ConstantParameter<double>>("G_a", G_a));
    return parameters;
}

std::vector<std::unique_ptr<ParameterLib::ParameterBase>>
setParametersForLinearElasticOrthotropic(std::vector<double> const& E0,
                                         std::vector<double> const& nu0,
                                         std::vector<double> const& G0)
{
    std::vector<std::unique_ptr<ParameterLib::ParameterBase>> parameters;
    parameters.push_back(
        std::make_unique<ParameterLib::ConstantParameter<double>>("E0", E0));
    parameters.push_back(
        std::make_unique<ParameterLib::ConstantParameter<double>>("nu0", nu0));
    parameters.push_back(
        std::make_unique<ParameterLib::ConstantParameter<double>>("G0", G0));
    return parameters;
}

std::vector<std::unique_ptr<ParameterLib::ParameterBase>>
setParametersForLinearElasticIsotropic(double const E, double const nu)
{
    std::vector<std::unique_ptr<ParameterLib::ParameterBase>> parameters;
    parameters.push_back(
        std::make_unique<ParameterLib::ConstantParameter<double>>("E", E));
    parameters.push_back(
        std::make_unique<ParameterLib::ConstantParameter<double>>("nu", nu));
    return parameters;
}

class LinearElasticTransverseIsotropic : public ::testing::Test
{
public:
    template <int Dim>
    void compareWithElasticOrthotropic(
        std::optional<ParameterLib::CoordinateSystem> const& coordinate_system)
    {
        // Create a LinearElasticTransverseIsotropic instance:
        auto const parameters_ti =
            setParametersForLinearElasticTransverseIsotropic(8.0e9, 4.0e9, 0.35,
                                                             0.25, 1.2e9);
        auto const elastic_model_transverse_isotropy =
            Tests::createTestConstitutiveRelation<
                MaterialLib::Solids::LinearElasticTransverseIsotropic<Dim>>(
                xml_ti, parameters_ti, coordinate_system, false,
                MaterialLib::Solids::createLinearElasticTransverseIsotropic<
                    Dim>);

        ParameterLib::SpatialPosition const pos;
        auto const C = elastic_model_transverse_isotropy->getElasticTensor(
            t_, pos, T_ref_);

        // Create a LinearElasticOrthotropic instance:
        auto const parameters_orth =
            getParametersForLinearElasticOrthotropic(Dim);

        auto const elastic_model_orthotropic =
            Tests::createTestConstitutiveRelation<
                MaterialLib::Solids::LinearElasticOrthotropic<Dim>>(
                xml_orth, parameters_orth, coordinate_system, false,
                MaterialLib::Solids::createLinearElasticOrthotropic<Dim>);
        auto const C_oth =
            elastic_model_orthotropic->getElasticTensor(t_, pos, T_ref_);

        // Compare the elastic tensor obtained by two models, respectively:
        ASSERT_LE((C - C_oth).norm() / C.norm(), 1e-14);

        MathLib::KelvinVector::KelvinMatrixType<Dim> Cel;

        // Compare the bulk modulus obtained by the transverse isotropic elastic
        // model with the expected value:
        double const k_ti =
            elastic_model_transverse_isotropy->getBulkModulus(t_, pos, &Cel);
        ASSERT_LE(std::abs(k_ti - 4301075268.8172045), 1e-14)
            << "Calculated bulk modulus by the transverse isotropy model: "
            << k_ti << "\n"
            << "Expected Bulk modulus: 4301075268.8172045";

        // The definitions of the bulk modulus by LinearElasticOrthotropic and
        // by LinearElasticTransverseIsotropic are different. Therefore, the
        // comparison of the bulk modulus values by the models are not
        // presented.
    }

    template <int Dimension>
    void compareWithLinearElasticIsotropic(
        std::optional<ParameterLib::CoordinateSystem> const& coordinate_system)
    {
        // Create an isotropic elastic model by using
        // LinearElasticTransverseIsotropic:
        double const E = 8.0e9;
        double const nu = 0.25;
        double const Ga = 0.5 * E / (1 + nu);
        auto const parameters_ti =
            setParametersForLinearElasticTransverseIsotropic(E, E, nu, nu, Ga);
        auto const elastic_model_transverse_isotropy =
            Tests::createTestConstitutiveRelation<
                MaterialLib::Solids::LinearElasticTransverseIsotropic<
                    Dimension>>(
                xml_ti, parameters_ti, coordinate_system, false,
                MaterialLib::Solids::createLinearElasticTransverseIsotropic<
                    Dimension>);
        ParameterLib::SpatialPosition const pos;
        auto const C_a = elastic_model_transverse_isotropy->getElasticTensor(
            t_, pos, T_ref_);

        // Create an isotropic elastic model by using LinearElasticIsotropic:
        auto parameters_iso = setParametersForLinearElasticIsotropic(E, nu);
        auto const elastic_model_linear_elastic_isotropic =
            Tests::createTestConstitutiveRelation<
                MaterialLib::Solids::LinearElasticIsotropic<Dimension>>(
                xml_iso, parameters_iso, false,
                MaterialLib::Solids::createLinearElasticIsotropic<Dimension>);
        auto const C_i =
            elastic_model_linear_elastic_isotropic->getElasticTensor(t_, pos,
                                                                     T_ref_);
        // Compare the elastic tensor obtained by two models, respectively:
        ASSERT_LE((C_a - C_i).norm() / C_a.norm(), 1e-14);

        MathLib::KelvinVector::KelvinMatrixType<Dimension> Cel;

        // Compare the bulk modulus obtained by obtained by two models,
        // respectively:
        double const k_ti =
            elastic_model_transverse_isotropy->getBulkModulus(t_, pos, &Cel);
        double const k_i =
            elastic_model_linear_elastic_isotropic->getBulkModulus(t_, pos,
                                                                   &Cel);
        ASSERT_LE(std::abs(k_ti - k_i), 1e-14)
            << "Calculated bulk modulus by the transverse isotropic elastic "
               "model: "
            << k_ti << "\n"
            << "Calculated bulk modulus by the isotropic elastic model:" << k_i;
    }

private:
    double const t_ = std::numeric_limits<double>::quiet_NaN();
    double const T_ref_ = std::numeric_limits<double>::quiet_NaN();

    std::vector<std::unique_ptr<ParameterLib::ParameterBase>>
    getParametersForLinearElasticOrthotropic(int const dim)
    {
        if (dim == 2)
        {
            // Since the model LinearElasticTransverseIsotropic defines the unit
            // direction of anisotropy as the second base (base2) of the 2D
            // local coordinate system, the following data are computed from
            // that for the  model LinearElasticTransverseIsotropic:
            std::vector<double> E0{8.0e9, 4.0e9, 8.0e9};
            std::vector<double> nu0{0.25, 0.125, 0.35};
            std::vector<double> G0{1.2e9, 0.0, 0.0};
            return setParametersForLinearElasticOrthotropic(E0, nu0, G0);
        }

        std::vector<double> E0{8.0e9, 8.0e9, 4.0e9};
        std::vector<double> nu0{0.35, 0.25, 0.25};
        std::vector<double> G0{2.962962962963e+09, 1.2e9, 1.2e9};
        return setParametersForLinearElasticOrthotropic(E0, nu0, G0);
    }
};

TEST_F(LinearElasticTransverseIsotropic, test_agaist_ElasticOrthotropic)
{
    {  // 2D
        ParameterLib::ConstantParameter<double> const e1{
            "e1", {0.8191520442889918, 0.573576436351046}};
        ParameterLib::ConstantParameter<double> const e2{
            "e2", {-0.573576436351046, 0.8191520442889918}};
        ParameterLib::CoordinateSystem const coordinate_system{e1, e2};

        compareWithElasticOrthotropic<2>(coordinate_system);
    }
    {  // 3D
        ParameterLib::ConstantParameter<double> const e1{
            "e1", {-0.8191520442889918, 0.0, -0.573576436351046}};
        ParameterLib::ConstantParameter<double> const e2{"e2",
                                                         {0.0, -1.0, 0.0}};
        ParameterLib::ConstantParameter<double> const e3{
            "e3", {-0.573576436351046, 0.0, 0.8191520442889918}};
        ParameterLib::CoordinateSystem const coordinate_system{e1, e2, e3};

        compareWithElasticOrthotropic<3>(coordinate_system);
    }
}

TEST_F(LinearElasticTransverseIsotropic,
       test_agaist_ElasticOrthotropicWithImplicitCoordinateBase)
{
    {  // 2D
        ParameterLib::ConstantParameter<double> const line_direction{
            "e3", {-0.573576436351046, 0.8191520442889918}};
        ParameterLib::CoordinateSystem const coordinate_system{line_direction};

        compareWithElasticOrthotropic<2>(coordinate_system);
    }
    {  // 3D
        ParameterLib::ConstantParameter<double> const line_direction{
            "e3", {-0.573576436351046, 0.0, 0.8191520442889918}};
        ParameterLib::CoordinateSystem const coordinate_system{line_direction};

        compareWithElasticOrthotropic<3>(coordinate_system);
    }
}

TEST_F(LinearElasticTransverseIsotropic, test_agaist_LinearElasticIsotropic)
{
    std::optional<ParameterLib::CoordinateSystem> coordinate_system = {};
    compareWithLinearElasticIsotropic<2>(coordinate_system);
    compareWithLinearElasticIsotropic<3>(coordinate_system);
}