Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include "4C_linalg_map.hpp"
#include "4C_linalg_sparsematrix.hpp"
#include "4C_linalg_vector.hpp"
#include "4C_red_airways_elementbase.hpp"
#include "4C_reduced_lung_test_utils_test.hpp"
#include "4C_unittest_utils_assertions_test.hpp"
#include "4C_utils_exceptions.hpp"
#include "4C_utils_function_manager.hpp"
Expand All @@ -36,29 +36,6 @@ namespace
using namespace FourC::ReducedLung;
using namespace FourC::ReducedLung::BoundaryConditions;

std::unique_ptr<Core::FE::Discretization> make_airway_discretization(
const std::vector<int>& node_ids, const std::vector<std::array<int, 2>>& element_nodes)
{
auto dis =
std::make_unique<Core::FE::Discretization>("boundary_conditions_test", MPI_COMM_WORLD, 3);

for (int node_id : node_ids)
{
std::array<double, 3> coords{static_cast<double>(node_id), 0.0, 0.0};
dis->add_node(coords, node_id, nullptr);
}

for (size_t i = 0; i < element_nodes.size(); ++i)
{
auto ele = std::make_shared<Discret::Elements::RedAirway>(static_cast<int>(i), 0);
ele->set_node_ids(2, element_nodes[i].data());
dis->add_element(ele);
}

dis->fill_complete(Core::FE::OptionsFillComplete::none());
return dis;
}

using InputBc = ReducedLungParameters::BoundaryConditions;

//! Boundary condition input together with the constrained nodes of the mesh it refers to.
Expand Down Expand Up @@ -199,7 +176,8 @@ namespace
BoundaryConditionFixture make_fixture()
{
BoundaryConditionFixture fixture;
fixture.discretization = make_airway_discretization({0, 1, 2}, {{0, 1}, {1, 2}});
fixture.discretization =
ReducedLung::TestUtils::make_chain_discretization("boundary_conditions_test", 2);
fixture.set_bc_input(make_constant_parameters());
fixture.ele_ids_per_node = {{0, {0}}, {1, {0, 1}}, {2, {1}}};
fixture.global_dof_per_ele = {{0, 3}, {1, 3}};
Expand Down
49 changes: 7 additions & 42 deletions src/reduced_lung/tests/4C_reduced_lung_helpers_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "4C_io_input_field.hpp"
#include "4C_linalg_map.hpp"
#include "4C_rebalance.hpp"
#include "4C_reduced_lung_test_utils_test.hpp"

#include <mpi.h>

Expand Down Expand Up @@ -127,45 +128,6 @@ namespace
return params;
}

std::unique_ptr<Core::FE::Discretization> make_discretization(
const std::vector<std::array<double, 3>>& node_coordinates,
const std::vector<std::array<int, 2>>& element_nodes, const char* name)
{
auto discretization = std::make_unique<Core::FE::Discretization>(name, MPI_COMM_WORLD, 3);
Core::Rebalance::RebalanceParameters rebalance_parameters;
build_discretization_from_nodes_and_elements(
*discretization, node_coordinates, element_nodes, rebalance_parameters);
discretization->fill_complete(Core::FE::OptionsFillComplete{
.assign_degrees_of_freedom = true,
.init_elements = true,
.do_boundary_conditions = false,
});
return discretization;
}

//! A straight chain of @p num_elements line2 elements with unit length along the x-axis.
std::unique_ptr<Core::FE::Discretization> make_chain_discretization(
const int num_elements, const char* name)
{
std::vector<std::array<double, 3>> node_coordinates;
std::vector<std::array<int, 2>> element_nodes;
for (int node_id = 0; node_id <= num_elements; ++node_id)
{
node_coordinates.push_back({static_cast<double>(node_id), 0.0, 0.0});
if (node_id > 0) element_nodes.push_back({node_id - 1, node_id});
}
return make_discretization(node_coordinates, element_nodes, name);
}

//! A single element splitting into two elements at its outlet node.
std::unique_ptr<Core::FE::Discretization> make_bifurcation_discretization(const char* name)
{
const std::vector<std::array<double, 3>> node_coordinates{
{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {2.0, 1.0, 0.0}, {2.0, -1.0, 0.0}};
const std::vector<std::array<int, 2>> element_nodes{{0, 1}, {1, 2}, {1, 3}};
return make_discretization(node_coordinates, element_nodes, name);
}

TEST(ReducedLungHelpersTests, CreateGlobalDofMapsBuildsOffsetsInElementOrder)
{
const std::map<int, int> local_dof_per_ele{{7, 3}, {1, 4}, {5, 2}};
Expand Down Expand Up @@ -308,7 +270,8 @@ namespace
TEST(ReducedLungHelpersTests, CreateLocalElementModelsBuildsModelContainers)
{
const auto params = make_setup_model_parameters();
auto discretization = make_chain_discretization(3, "local_element_models_test");
auto discretization =
ReducedLung::TestUtils::make_chain_discretization("local_element_models_test", 3);

Airways::AirwayContainer airways;
TerminalUnits::TerminalUnitContainer terminal_units;
Expand Down Expand Up @@ -355,7 +318,8 @@ namespace
TEST(ReducedLungHelpersTests, CreateLocalElementModelsUsesSelectedModelStateCount)
{
const auto params = make_revisited_airway_model_parameters();
auto discretization = make_chain_discretization(4, "revisited_airway_model_test");
auto discretization =
ReducedLung::TestUtils::make_chain_discretization("revisited_airway_model_test", 4);

Airways::AirwayContainer airways;
TerminalUnits::TerminalUnitContainer terminal_units;
Expand All @@ -377,7 +341,8 @@ namespace

TEST(ReducedLungHelpersTests, CreateGlobalEleIdsPerNodeCollectsAdjacency)
{
auto discretization = make_bifurcation_discretization("global_ele_ids_test");
auto discretization =
ReducedLung::TestUtils::make_bifurcation_discretization("global_ele_ids_test");
auto global_ele_ids_per_node = create_global_ele_ids_per_node(*discretization, MPI_COMM_WORLD);

ASSERT_EQ(global_ele_ids_per_node.size(), 4u);
Expand Down
45 changes: 12 additions & 33 deletions src/reduced_lung/tests/4C_reduced_lung_junctions_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include "4C_linalg_map.hpp"
#include "4C_linalg_sparsematrix.hpp"
#include "4C_linalg_vector.hpp"
#include "4C_red_airways_elementbase.hpp"
#include "4C_reduced_lung_test_utils_test.hpp"
#include "4C_unittest_utils_assertions_test.hpp"
#include "4C_utils_exceptions.hpp"

Expand Down Expand Up @@ -55,28 +55,6 @@ namespace
}
}

std::unique_ptr<Core::FE::Discretization> make_airway_discretization(
const std::vector<int>& node_ids, const std::vector<std::array<int, 2>>& element_nodes)
{
auto dis = std::make_unique<Core::FE::Discretization>("junctions_test", MPI_COMM_WORLD, 3);

for (int node_id : node_ids)
{
std::array<double, 3> coords{static_cast<double>(node_id), 0.0, 0.0};
dis->add_node(coords, node_id, nullptr);
}

for (size_t i = 0; i < element_nodes.size(); ++i)
{
auto ele = std::make_shared<Discret::Elements::RedAirway>(static_cast<int>(i), 0);
ele->set_node_ids(2, element_nodes[i].data());
dis->add_element(ele);
}

dis->fill_complete(Core::FE::OptionsFillComplete::none());
return dis;
}

TEST(JunctionsTests, ConnectionResidualAssembly)
{
ConnectionData connections;
Expand Down Expand Up @@ -226,9 +204,9 @@ namespace
GTEST_SKIP() << "Junction creation tests require a serial communicator.";
}

auto dis = make_airway_discretization({1, 2, 3}, {{1, 2}, {2, 3}});
auto dis = ReducedLung::TestUtils::make_chain_discretization("junctions_test", 2);

std::map<int, std::vector<int>> ele_ids_per_node{{1, {0}}, {2, {0, 1}}, {3, {1}}};
std::map<int, std::vector<int>> ele_ids_per_node{{0, {0}}, {1, {0, 1}}, {2, {1}}};
std::map<int, int> global_dof_per_ele{{0, 3}, {1, 3}};
std::map<int, int> first_global_dof_of_ele{{0, 0}, {1, 3}};

Expand Down Expand Up @@ -256,9 +234,9 @@ namespace
GTEST_SKIP() << "Junction creation tests require a serial communicator.";
}

auto dis = make_airway_discretization({1, 2, 3, 4}, {{1, 2}, {2, 3}, {2, 4}});
auto dis = ReducedLung::TestUtils::make_bifurcation_discretization("junctions_test");

std::map<int, std::vector<int>> ele_ids_per_node{{1, {0}}, {2, {0, 1, 2}}, {3, {1}}, {4, {2}}};
std::map<int, std::vector<int>> ele_ids_per_node{{0, {0}}, {1, {0, 1, 2}}, {2, {1}}, {3, {2}}};
std::map<int, int> global_dof_per_ele{{0, 3}, {1, 3}, {2, 3}};
std::map<int, int> first_global_dof_of_ele{{0, 0}, {1, 3}, {2, 6}};

Expand Down Expand Up @@ -287,9 +265,9 @@ namespace
GTEST_SKIP() << "Junction creation tests require a serial communicator.";
}

auto dis = make_airway_discretization({1, 2, 3}, {{1, 2}, {2, 3}});
auto dis = ReducedLung::TestUtils::make_chain_discretization("junctions_test", 2);

std::map<int, std::vector<int>> ele_ids_per_node{{1, {0}}, {3, {1}}};
std::map<int, std::vector<int>> ele_ids_per_node{{0, {0}}, {2, {1}}};
std::map<int, int> global_dof_per_ele{{0, 3}, {1, 3}};
std::map<int, int> first_global_dof_of_ele{{0, 0}, {1, 3}};

Expand All @@ -310,9 +288,10 @@ namespace
GTEST_SKIP() << "Junction creation tests require a serial communicator.";
}

auto dis = make_airway_discretization({1, 2, 3}, {{1, 2}, {3, 2}});
auto dis = ReducedLung::TestUtils::make_line2_discretization(
"junctions_test", {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {2.0, 0.0, 0.0}}, {{0, 1}, {2, 1}});

std::map<int, std::vector<int>> ele_ids_per_node{{1, {0}}, {2, {0, 1}}, {3, {1}}};
std::map<int, std::vector<int>> ele_ids_per_node{{0, {0}}, {1, {0, 1}}, {2, {1}}};
std::map<int, int> global_dof_per_ele{{0, 3}, {1, 3}};
std::map<int, int> first_global_dof_of_ele{{0, 0}, {1, 3}};

Expand All @@ -333,9 +312,9 @@ namespace
GTEST_SKIP() << "Junction creation tests require a serial communicator.";
}

auto dis = make_airway_discretization({1, 2, 3}, {{1, 2}, {2, 3}});
auto dis = ReducedLung::TestUtils::make_chain_discretization("junctions_test", 2);

std::map<int, std::vector<int>> ele_ids_per_node{{1, {0}}, {2, {0, 1, 2, 3}}, {3, {1}}};
std::map<int, std::vector<int>> ele_ids_per_node{{0, {0}}, {1, {0, 1, 2, 3}}, {2, {1}}};
std::map<int, int> global_dof_per_ele{{0, 3}, {1, 3}};
std::map<int, int> first_global_dof_of_ele{{0, 0}, {1, 3}};

Expand Down
57 changes: 57 additions & 0 deletions src/reduced_lung/tests/4C_reduced_lung_test_utils_test.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,76 @@

#include "4C_config.hpp"

#include "4C_fem_discretization.hpp"
#include "4C_linalg_map.hpp"
#include "4C_linalg_sparsematrix.hpp"
#include "4C_linalg_vector.hpp"
#include "4C_rebalance.hpp"
#include "4C_reduced_lung_airways.hpp"
#include "4C_reduced_lung_helpers.hpp"
#include "4C_reduced_lung_terminal_unit.hpp"

#include <mpi.h>

#include <array>
#include <memory>
Comment thread
maxiludwig marked this conversation as resolved.
#include <string>
#include <vector>

FOUR_C_NAMESPACE_OPEN

namespace ReducedLung::TestUtils
{
/**
* Build a line2 discretization from nodal coordinates and connectivity, using the same routine
* as the production code. Nodes and elements get 0-based ids in the order they are passed;
* @p element_nodes is the connectivity [node_in, node_out] referring to those node ids.
*/
inline std::unique_ptr<Core::FE::Discretization> make_line2_discretization(
const std::string& name, const std::vector<std::array<double, 3>>& node_coordinates,
const std::vector<std::array<int, 2>>& element_nodes)
{
auto discretization = std::make_unique<Core::FE::Discretization>(name, MPI_COMM_WORLD, 3);
const Core::Rebalance::RebalanceParameters rebalance_parameters{};
build_discretization_from_nodes_and_elements(
*discretization, node_coordinates, element_nodes, rebalance_parameters);
discretization->fill_complete(Core::FE::OptionsFillComplete{
.assign_degrees_of_freedom = true,
.init_elements = true,
.do_boundary_conditions = false,
});

return discretization;
}

/**
* Build a straight line discretization along the x-axis with 0-based node ids.
* The discretization is bifurcation-free consisting of @p num_elements line2 elements of unit
* length.
*/
inline std::unique_ptr<Core::FE::Discretization> make_chain_discretization(
const std::string& name, const int num_elements)
{
std::vector<std::array<double, 3>> node_coordinates;
std::vector<std::array<int, 2>> element_nodes;
for (int node_id = 0; node_id <= num_elements; ++node_id)
{
node_coordinates.push_back({static_cast<double>(node_id), 0.0, 0.0});
if (node_id > 0) element_nodes.push_back({node_id - 1, node_id});
}
return make_line2_discretization(name, node_coordinates, element_nodes);
}

//! A single element splitting into two elements at its outlet node.
inline std::unique_ptr<Core::FE::Discretization> make_bifurcation_discretization(
const std::string& name)
{
const std::vector<std::array<double, 3>> node_coordinates{
{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {2.0, 1.0, 0.0}, {2.0, -1.0, 0.0}};
const std::vector<std::array<int, 2>> element_nodes{{0, 1}, {1, 2}, {1, 3}};
return make_line2_discretization(name, node_coordinates, element_nodes);
}

// Generalized helper to check a Jacobian column against a central finite-difference
// approximation of the residual. Works for both TerminalUnitModel and AirwayModel as long
// as the model exposes `data`, `residual_evaluator` and the data structure
Expand Down
Loading