https://gitlab.opengeosys.org/ogs/ogs.git
Raw File
Tip revision: fdc77c81aae262b878c0a12ea1f864d63b881e82 authored by Tom Fischer on 18 December 2020, 15:11:56 UTC
Merge branch 'LiquidFlowRenameStorageToBulkCompressibility' into 'master'
Tip revision: fdc77c8
MeshProperties.cpp
/**
 * \file
 * \copyright
 * Copyright (c) 2012-2020, 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 <numeric>

#include <Eigen/Eigen>

#include "gtest/gtest.h"

#include "MeshLib/MeshGenerators/MeshGenerator.h"
#include "MeshLib/Mesh.h"
#include "MeshLib/Elements/Element.h"
#include "MeshLib/PropertyVector.h"

class MeshLibProperties : public ::testing::Test
{
public:
    MeshLibProperties()
    {
        mesh = MeshLib::MeshGenerator::generateRegularHexMesh(1.0, mesh_size);
    }

    ~MeshLibProperties() override { delete mesh; }
    static std::size_t const mesh_size = 5;
    MeshLib::Mesh* mesh{nullptr};
};
std::size_t const MeshLibProperties::mesh_size;

TEST_F(MeshLibProperties, PropertyVectorTestMetaData)
{
    ASSERT_TRUE(mesh != nullptr);

    std::string const prop_name("TestProperty");
    auto const* const p = mesh->getProperties().createNewPropertyVector<double>(
        prop_name, MeshLib::MeshItemType::Cell);

    ASSERT_EQ(0u, p->getPropertyName().compare(prop_name));
    ASSERT_EQ(MeshLib::MeshItemType::Cell, p->getMeshItemType());
    ASSERT_EQ(1u, p->getNumberOfGlobalComponents());
    ASSERT_EQ(0u, p->size());
}

TEST_F(MeshLibProperties, PropertyVectorTestIntegrationPoint)
{
    ASSERT_TRUE(mesh != nullptr);

    int const n_integration_points = 4;
    int const vector_length = 6;
    std::string const prop_name("ip_field");

    auto* const p_ptr = mesh->getProperties().createNewPropertyVector<double>(
        prop_name, MeshLib::MeshItemType::IntegrationPoint, vector_length);
    ASSERT_TRUE(p_ptr != nullptr);

    auto& p = *p_ptr;
    ASSERT_EQ(p.getPropertyName(), prop_name);
    ASSERT_EQ(MeshLib::MeshItemType::IntegrationPoint, p.getMeshItemType());
    ASSERT_EQ(vector_length, p.getNumberOfGlobalComponents());
    ASSERT_EQ(0u, p.size());

    // Fill the property vector with double data in following pattern:
    // for element's id xx and integration point number yy the value is xx.yy.
    p.resize(mesh->getNumberOfElements() * n_integration_points);

    std::vector<std::size_t> offsets(mesh->getNumberOfElements());
    std::size_t offset = 0; // last position in the property vector
    for (auto const& e : mesh->getElements())
    {
        offsets[e->getID()] = offset;
        for (int ip = 0; ip < n_integration_points; ++ip)
        {
            p[offset + ip] = e->getID() + ip * 0.01;
        }
        offset += n_integration_points;
    }

    // Check the values at each offset.

    // Last element is checked after the for-loop.
    std::size_t i = 0;
    for (; i < offsets.size() - 1; ++i)
    {
        std::size_t const size = offsets[i + 1] - offsets[i];
        ASSERT_EQ(n_integration_points, size);
        for (int ip = 0; ip < n_integration_points; ++ip)
        {
            ASSERT_EQ(i + ip * 0.01, p[offsets[i] + ip]);
        }
    }
    {  // Last element
        std::size_t const size = p.size() - offsets[i];
        ASSERT_EQ(n_integration_points, size);
        for (int ip = 0; ip < n_integration_points; ++ip)
        {
            ASSERT_EQ(i + ip * 0.01, p[offsets[i] + ip]);
        }
    }
}

TEST_F(MeshLibProperties, AddDoubleProperties)
{
    ASSERT_TRUE(mesh != nullptr);
    const std::size_t size(mesh_size*mesh_size*mesh_size);

    std::string const prop_name("TestProperty");
    auto* const double_properties =
        mesh->getProperties().createNewPropertyVector<double>(
            prop_name, MeshLib::MeshItemType::Cell);
    ASSERT_EQ(0u, double_properties->size());

    double_properties->resize(size);
    ASSERT_EQ(size, double_properties->size());

    std::iota(double_properties->begin(), double_properties->end(), 1);
    for (std::size_t k(0); k<size; k++) {
        ASSERT_EQ(static_cast<double>(k+1), (*double_properties)[k]);
    }

    ASSERT_TRUE(mesh->getProperties().existsPropertyVector<double>(prop_name));
    auto* const double_properties_cpy =
        mesh->getProperties().getPropertyVector<double>(prop_name);
    for (std::size_t k(0); k<size; k++) {
        ASSERT_EQ((*double_properties)[k], (*double_properties_cpy)[k]);
    }

    mesh->getProperties().removePropertyVector(prop_name);
    ASSERT_FALSE(mesh->getProperties().existsPropertyVector<double>(prop_name));
}

TEST_F(MeshLibProperties, AddDoublePointerProperties)
{
    ASSERT_TRUE(mesh != nullptr);
    std::string const& prop_name("GroupProperty");
    // check if a property with the name is already assigned to the mesh
    ASSERT_FALSE(mesh->getProperties().hasPropertyVector(prop_name));
    // data needed for the property
    const std::size_t n_prop_val_groups(10);
    const std::size_t n_items(mesh_size*mesh_size*mesh_size);
    std::vector<std::size_t> prop_item2group_mapping(n_items);
    // create simple mat_group to index mapping
    for (std::size_t j(0); j<n_prop_val_groups; j++) {
        auto const lower(static_cast<std::size_t>(
            (static_cast<double>(j) / n_prop_val_groups) * n_items));
        auto const upper(static_cast<std::size_t>(
            (static_cast<double>(j + 1) / n_prop_val_groups) * n_items));
        for (std::size_t k(lower); k < upper; k++)
        {
            prop_item2group_mapping[k] = j;
        }
    }
    // obtain PropertyVector data structure
    auto* const group_properties =
        mesh->getProperties().createNewPropertyVector<double*>(
            prop_name, n_prop_val_groups, prop_item2group_mapping,
            MeshLib::MeshItemType::Cell);
    ASSERT_EQ(prop_item2group_mapping.size(), group_properties->size());

    // initialize the property values
    for (std::size_t i(0); i<n_prop_val_groups; i++) {
        group_properties->initPropertyValue(i, static_cast<double>(i+1));
    }
    // check mapping to values
    for (std::size_t i(0); i<n_prop_val_groups; i++) {
        auto const lower(static_cast<std::size_t>(
            (static_cast<double>(i) / n_prop_val_groups) * n_items));
        auto const upper(static_cast<std::size_t>(
            (static_cast<double>(i + 1) / n_prop_val_groups) * n_items));
        for (std::size_t k(lower); k < upper; k++)
        {
            ASSERT_NEAR(static_cast<double>(i + 1), *(*group_properties)[k],
                        std::numeric_limits<double>::epsilon());
        }
    }

    // the mesh should have the property assigned to cells
    ASSERT_TRUE(mesh->getProperties().hasPropertyVector(prop_name));
    // fetch the properties from the container
    auto const* const group_properties_cpy =
        mesh->getProperties().getPropertyVector<double*>(prop_name);
    ASSERT_FALSE(!group_properties_cpy);

    for (std::size_t k(0); k<n_items; k++) {
        ASSERT_EQ((*group_properties)[k], (*group_properties_cpy)[k]);
    }

    mesh->getProperties().removePropertyVector(prop_name);
    ASSERT_FALSE(
        mesh->getProperties().existsPropertyVector<double*>(prop_name));
}

TEST_F(MeshLibProperties, AddArrayPointerProperties)
{
    ASSERT_TRUE(mesh != nullptr);
    std::string const& prop_name("GroupPropertyWithArray");
    const std::size_t n_prop_val_groups(10);
    const std::size_t n_items(mesh_size*mesh_size*mesh_size);
    std::vector<std::size_t> prop_item2group_mapping(n_items);
    // create simple mat_group to index mapping
    for (std::size_t j(0); j<n_prop_val_groups; j++) {
        auto const lower(static_cast<std::size_t>(
            (static_cast<double>(j) / n_prop_val_groups) * n_items));
        auto const upper(static_cast<std::size_t>(
            (static_cast<double>(j + 1) / n_prop_val_groups) * n_items));
        for (std::size_t k(lower); k < upper; k++)
        {
            prop_item2group_mapping[k] = j;
        }
    }
    auto* const group_prop_vec =
        mesh->getProperties().createNewPropertyVector<std::array<double, 3>*>(
            prop_name, n_prop_val_groups, prop_item2group_mapping,
            MeshLib::MeshItemType::Cell);
    ASSERT_EQ(prop_item2group_mapping.size(), group_prop_vec->size());

    // initialize the property values
    for (std::size_t i(0); i<n_prop_val_groups; i++) {
        group_prop_vec->initPropertyValue(i,
            std::array<double,3>({{static_cast<double>(i),
                static_cast<double>(i+1),
                static_cast<double>(i+2)}}
            )
        );
    }
    // check the mapping to values
    for (std::size_t i(0); i<n_prop_val_groups; i++) {
        auto const lower(static_cast<std::size_t>(
            (static_cast<double>(i) / n_prop_val_groups) * n_items));
        auto const upper(static_cast<std::size_t>(
            (static_cast<double>(i + 1) / n_prop_val_groups) * n_items));
        for (std::size_t k(lower); k < upper; k++)
        {
            ASSERT_NEAR(static_cast<double>(i), (*(*group_prop_vec)[k])[0],
                        std::numeric_limits<double>::epsilon());
            ASSERT_NEAR(static_cast<double>(i + 1), (*(*group_prop_vec)[k])[1],
                        std::numeric_limits<double>::epsilon());
            ASSERT_NEAR(static_cast<double>(i + 2), (*(*group_prop_vec)[k])[2],
                        std::numeric_limits<double>::epsilon());
        }
    }

    auto* const group_properties_cpy =
        mesh->getProperties().getPropertyVector<std::array<double, 3>*>(
            prop_name);
    ASSERT_FALSE(!group_properties_cpy);

    for (std::size_t k(0); k<n_items; k++) {
        ASSERT_EQ((*((*group_prop_vec)[k]))[0],
            (*((*group_properties_cpy)[k]))[0]);
        ASSERT_EQ((*((*group_prop_vec)[k]))[1],
            (*((*group_properties_cpy)[k]))[1]);
        ASSERT_EQ((*((*group_prop_vec)[k]))[2],
            (*((*group_properties_cpy)[k]))[2]);
    }

    mesh->getProperties().removePropertyVector(prop_name);
    auto exists =
        mesh->getProperties().existsPropertyVector<std::array<double, 3>*>(
            prop_name);
    ASSERT_FALSE(exists);
}

TEST_F(MeshLibProperties, AddVariousDifferentProperties)
{
    ASSERT_TRUE(mesh != nullptr);

    std::string const& prop_name("GroupVectorProperty");
    // check if the property is already assigned to the mesh
    ASSERT_FALSE(mesh->getProperties().hasPropertyVector(prop_name));
    const std::size_t n_prop_val_groups(10);
    const std::size_t n_items(mesh_size*mesh_size*mesh_size);
    std::vector<std::size_t> prop_item2group_mapping(n_items);
    // create simple mat_group to index mapping
    for (std::size_t j(0); j<n_prop_val_groups; j++) {
        auto const lower(static_cast<std::size_t>(
            (static_cast<double>(j) / n_prop_val_groups) * n_items));
        auto const upper(static_cast<std::size_t>(
            (static_cast<double>(j + 1) / n_prop_val_groups) * n_items));
        for (std::size_t k(lower); k < upper; k++)
        {
            prop_item2group_mapping[k] = j;
        }
    }
    // create data structure for the property
    auto* const group_properties =
        mesh->getProperties().createNewPropertyVector<std::array<double, 3>*>(
            prop_name, n_prop_val_groups, prop_item2group_mapping,
            MeshLib::MeshItemType::Cell);
    // initialize the property values
    for (std::size_t i(0); i<n_prop_val_groups; i++) {
        group_properties->initPropertyValue(i,
            std::array<double,3>({{static_cast<double>(i),
                static_cast<double>(i+1),
                static_cast<double>(i+2)}}
            )
        );
    }

    // the mesh should have the property assigned to cells
    ASSERT_TRUE(mesh->getProperties().hasPropertyVector(prop_name));

    // fetch the vector filled with property values from mesh
    auto const* const group_properties_cpy =
        mesh->getProperties().getPropertyVector<std::array<double, 3>*>(
            prop_name);
    ASSERT_FALSE(!group_properties_cpy);
    // compare the content
    const std::size_t n_elements(mesh_size*mesh_size*mesh_size);
    for (std::size_t k(0); k<n_elements; k++) {
        ASSERT_EQ((*((*group_properties)[k]))[0],
            (*((*group_properties_cpy)[k]))[0]);
        ASSERT_EQ((*((*group_properties)[k]))[1],
            (*((*group_properties_cpy))[k])[1]);
        ASSERT_EQ((*((*group_properties)[k]))[2],
            (*((*group_properties_cpy)[k]))[2]);
    }

    // *** add a 2nd property ***
    std::string const& prop_name_2("ItemwiseMatrixProperties");
    // check if the property is already assigned to the mesh
    ASSERT_FALSE(mesh->getProperties().hasPropertyVector(prop_name_2));
    const std::size_t n_items_2(mesh_size*mesh_size*mesh_size);
    auto* const array_properties =
        mesh->getProperties().createNewPropertyVector<std::array<float, 9>>(
            prop_name_2, MeshLib::MeshItemType::Cell);

    array_properties->resize(n_items_2);

    // initialize the property values
    for (std::size_t i(0); i<n_items_2; i++) {
        // init property value
        for (std::size_t k(0); k<(*array_properties)[i].size(); k++) {
            (*array_properties)[i][k] = static_cast<float>(i+k);
        }
    }

    EXPECT_EQ(9, (*array_properties)[0].size());

    // the mesh should have the property assigned to cells
    ASSERT_TRUE(mesh->getProperties().hasPropertyVector(prop_name_2));

    // fetch the vector in order to compare the content
    auto const* const array_properties_cpy =
        mesh->getProperties().getPropertyVector<std::array<float, 9>>(
            prop_name_2);
    ASSERT_FALSE(!array_properties_cpy);

    // compare the values/matrices
    for (std::size_t k(0); k<n_items_2; k++) {
        for (std::size_t j(0); j<(*array_properties)[k].size(); j++) {
            ASSERT_EQ((*array_properties)[k][j], (*array_properties_cpy)[k][j]);
        }
    }

    // *** add a 3rd property ***
    std::string const& prop_name_3("ItemwiseEigenMatrixProperties");
    // check if the property is already assigned to the mesh
    ASSERT_FALSE(mesh->getProperties().hasPropertyVector(prop_name_3));
    auto* const matrix_properties =
        mesh->getProperties()
            .createNewPropertyVector<
                Eigen::Matrix<double, 3, 3, Eigen::RowMajor>>(
                prop_name_3, MeshLib::MeshItemType::Cell);
    // init property values
    for (auto it = matrix_properties->begin(); it != matrix_properties->end();
         it++)
    {
        for (int r(0); r<it->rows(); r++) {
            for (int c(0); c<it->cols(); c++) {
                (*it)(r,c) = static_cast<double>(
                    std::distance(matrix_properties->begin(),it)+r*it->cols()+c+1);
            }
        }
    }

    // the mesh should have the property assigned to cells
    ASSERT_TRUE(mesh->getProperties().hasPropertyVector(prop_name_3));

    // fetch the vector in order to compare the content
    auto const* const matrix_properties_cpy =
        mesh->getProperties()
            .getPropertyVector<Eigen::Matrix<double, 3, 3, Eigen::RowMajor>>(
                prop_name_3);
    ASSERT_FALSE(!matrix_properties_cpy);

    // compare the values/matrices
    auto it_cpy = matrix_properties_cpy->begin();
    for (auto it = matrix_properties->begin(); it != matrix_properties->end();
         it++, it_cpy++)
    {
        for (int r(0); r<it->rows(); r++) {
            for (int c(0); c<it->cols(); c++) {
                ASSERT_EQ((*it)(r,c), (*it_cpy)(r,c));
            }
        }
    }
}

TEST_F(MeshLibProperties, CopyConstructor)
{
    ASSERT_TRUE(mesh != nullptr);
    std::string const& prop_name("GroupProperty");
    // data needed for the property
    const std::size_t n_prop_val_groups(10);
    const std::size_t n_items(mesh_size*mesh_size*mesh_size);
    std::vector<std::size_t> prop_item2group_mapping(n_items);
    // create simple mat_group to index mapping
    for (std::size_t j(0); j<n_prop_val_groups; j++) {
        auto const lower(static_cast<std::size_t>(
            (static_cast<double>(j) / n_prop_val_groups) * n_items));
        auto const upper(static_cast<std::size_t>(
            (static_cast<double>(j + 1) / n_prop_val_groups) * n_items));
        for (std::size_t k(lower); k < upper; k++)
        {
            prop_item2group_mapping[k] = j;
        }
    }
    // obtain PropertyVector data structure
    auto* const group_properties(
        mesh->getProperties().createNewPropertyVector<double*>(
            prop_name, n_prop_val_groups, prop_item2group_mapping,
            MeshLib::MeshItemType::Cell
        )
    );
    // initialize the property values
    for (std::size_t i(0); i<n_prop_val_groups; i++) {
        group_properties->initPropertyValue(i, static_cast<double>(i + 1));
    }

    // create a copy from the original Properties object
    MeshLib::Properties properties_copy(mesh->getProperties());
    // check if the Properties have a PropertyVector with the correct name
    ASSERT_TRUE(properties_copy.hasPropertyVector(prop_name));
    // fetch the PropertyVector from the copy of the Properties object
    auto const* const group_properties_cpy(
        properties_copy.getPropertyVector<double*>(prop_name));
    ASSERT_FALSE(!group_properties_cpy);

    // check if the values in the PropertyVector of the copy of the Properties
    // are the same
    for (std::size_t k(0); k<n_items; k++) {
        EXPECT_EQ(*(*group_properties)[k], *(*group_properties_cpy)[k]);
    }
}

TEST_F(MeshLibProperties, AddDoublePropertiesTupleSize2)
{
    ASSERT_TRUE(mesh != nullptr);
    const std::size_t number_of_tuples(mesh_size*mesh_size*mesh_size);

    std::string const prop_name("TestProperty");
    auto* const pv = mesh->getProperties().createNewPropertyVector<double>(
        prop_name, MeshLib::MeshItemType::Cell, 2);
    // PropertyVector should be created in a correct way
    ASSERT_NE(nullptr, pv);

    ASSERT_EQ(0u, pv->getPropertyName().compare(prop_name));
    ASSERT_EQ(MeshLib::MeshItemType::Cell, pv->getMeshItemType());
    ASSERT_EQ(2u, pv->getNumberOfGlobalComponents());
    ASSERT_EQ(0u, pv->getNumberOfTuples());
    ASSERT_EQ(0u, pv->size());

    // push some values (2 tuples) into the vector
    for (std::size_t k(0); k<number_of_tuples; k++) {
        pv->push_back(static_cast<double>(k));
        pv->push_back(static_cast<double>(k));
    }
    // check the number of tuples
    ASSERT_EQ(number_of_tuples, pv->getNumberOfTuples());
    ASSERT_EQ(pv->getNumberOfTuples() * pv->getNumberOfGlobalComponents(),
              pv->size());
    // check the values
    for (std::size_t k(0); k<number_of_tuples; k++) {
        ASSERT_EQ(static_cast<double>(k), (*pv)[2*k]);
        ASSERT_EQ(static_cast<double>(k), (*pv)[2*k+1]);
    }
}


back to top