Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix cartesian_product dox #4700

Merged
merged 2 commits into from
Feb 8, 2023
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
6 changes: 6 additions & 0 deletions src/Utilities/CartesianProduct.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ void insert_tuples(Op op, std::pair<InputIterator1, InputIterator1> head,
} // namespace detail

/*!
* \ingroup UtilitiesGroup
* \brief Fill the `result` iterator with the Cartesian product of a sequence of
* iterators
*
Expand All @@ -54,10 +55,15 @@ void cartesian_product(OutputIterator result,
}

/*!
* \ingroup UtilitiesGroup
* \brief The Cartesian product of a sequence arrays
*
* Returns a `std::array` with all possible combinations of the input arrays.
* The last dimension varies fastest.
*
* \example
* Here's an example using this function to replace a nested for loop:
* \snippet Test_Wedge3D.cpp cartesian_product_loop
*/
template <typename... Ts, size_t... Lens>
std::array<std::tuple<Ts...>, (... * Lens)> cartesian_product(
Expand Down
2 changes: 2 additions & 0 deletions tests/Unit/Domain/CoordinateMaps/Test_Wedge3D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,15 @@ void test_wedge3d_all_directions() {
using WedgeHalves = Wedge3D::WedgeHalves;
const std::array<WedgeHalves, 3> halves_array = {
{WedgeHalves::UpperOnly, WedgeHalves::LowerOnly, WedgeHalves::Both}};
// [cartesian_product_loop]
for (const auto& [halves, orientation, with_equiangular_map,
radial_distribution] :
cartesian_product(halves_array, all_wedge_directions(),
make_array(true, false),
make_array(CoordinateMaps::Distribution::Linear,
CoordinateMaps::Distribution::Logarithmic,
CoordinateMaps::Distribution::Inverse))) {
// [cartesian_product_loop]
CAPTURE(halves);
CAPTURE(orientation);
CAPTURE(with_equiangular_map);
Expand Down
302 changes: 148 additions & 154 deletions tests/Unit/Domain/Creators/Test_Cylinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "Helpers/Domain/Creators/TestHelpers.hpp"
#include "Helpers/Domain/DomainTestHelpers.hpp"
#include "Parallel/RegisterDerivedClassesWithCharm.hpp"
#include "Utilities/CartesianProduct.hpp"
#include "Utilities/MakeArray.hpp"

namespace domain {
Expand Down Expand Up @@ -238,87 +239,85 @@ void test_cylinder_no_refinement() {
domain::CoordinateMaps::Distribution::Linear};
const std::vector distribution_in_z{
domain::CoordinateMaps::Distribution::Linear};
for (const bool with_boundary_conditions : {true, false}) {
for (const auto& [with_boundary_conditions, equiangular_map, periodic_in_z] :
cartesian_product(make_array(true, false), make_array(true, false),
make_array(true, false))) {
CAPTURE(with_boundary_conditions);
for (const bool equiangular_map : {true, false}) {
CAPTURE(equiangular_map);
for (const bool periodic_in_z : {true, false}) {
CAPTURE(periodic_in_z);
const double inner_radius = 1.0;
const double outer_radius = 2.0;
const double lower_z_bound = -2.5;
const double upper_z_bound = 5.0;
const size_t refinement_level = 2;
const std::array<size_t, 3> grid_points{{4, 4, 3}};
CAPTURE(equiangular_map);
CAPTURE(periodic_in_z);
const double inner_radius = 1.0;
const double outer_radius = 2.0;
const double lower_z_bound = -2.5;
const double upper_z_bound = 5.0;
const size_t refinement_level = 2;
const std::array<size_t, 3> grid_points{{4, 4, 3}};

const auto cylinder =
with_boundary_conditions
? creators::Cylinder{inner_radius,
outer_radius,
lower_z_bound,
upper_z_bound,
periodic_in_z
? std::make_unique<PeriodicBc>()
: create_lower_z_boundary_condition(),
periodic_in_z
? std::make_unique<PeriodicBc>()
: create_upper_z_boundary_condition(),
create_mantle_boundary_condition(),
refinement_level,
grid_points,
equiangular_map,
{},
{}}
: creators::Cylinder{inner_radius,
outer_radius,
lower_z_bound,
upper_z_bound,
periodic_in_z,
refinement_level,
grid_points,
equiangular_map,
{},
{}};
const auto domain = TestHelpers::domain::creators::test_domain_creator(
cylinder, with_boundary_conditions, periodic_in_z);
const auto cylinder =
with_boundary_conditions
? creators::Cylinder{inner_radius,
outer_radius,
lower_z_bound,
upper_z_bound,
periodic_in_z
? std::make_unique<PeriodicBc>()
: create_lower_z_boundary_condition(),
periodic_in_z
? std::make_unique<PeriodicBc>()
: create_upper_z_boundary_condition(),
create_mantle_boundary_condition(),
refinement_level,
grid_points,
equiangular_map,
{},
{}}
: creators::Cylinder{inner_radius,
outer_radius,
lower_z_bound,
upper_z_bound,
periodic_in_z,
refinement_level,
grid_points,
equiangular_map,
{},
{}};
const auto domain = TestHelpers::domain::creators::test_domain_creator(
cylinder, with_boundary_conditions, periodic_in_z);

CHECK(cylinder.block_names() ==
std::vector<std::string>{"InnerCube", "East", "North", "West",
"South"});
CHECK(cylinder.block_groups() ==
std::unordered_map<std::string, std::unordered_set<std::string>>{
{"Wedges", {"East", "North", "West", "South"}}});
CHECK(cylinder.block_names() == std::vector<std::string>{"InnerCube",
"East", "North",
"West", "South"});
CHECK(cylinder.block_groups() ==
std::unordered_map<std::string, std::unordered_set<std::string>>{
{"Wedges", {"East", "North", "West", "South"}}});

test_cylinder_construction(cylinder, inner_radius, outer_radius,
lower_z_bound, upper_z_bound, periodic_in_z,
{5, grid_points},
{5, make_array<3>(refinement_level)},
equiangular_map, with_boundary_conditions);
test_cylinder_construction(
cylinder, inner_radius, outer_radius, lower_z_bound, upper_z_bound,
periodic_in_z, {5, grid_points}, {5, make_array<3>(refinement_level)},
equiangular_map, with_boundary_conditions);

const std::string opt_string{
"Cylinder:\n"
" InnerRadius: 1.0\n"
" OuterRadius: 2.0\n"
" LowerZBound: -2.5\n"
" UpperZBound: 5.0\n"
" InitialRefinement: 2\n"
" InitialGridPoints: [4,4,3]\n"
" UseEquiangularMap: " +
std::string{equiangular_map ? "true" : "false"} +
"\n"
" RadialPartitioning: []\n"
" PartitioningInZ: []\n"
" RadialDistribution: [Linear]\n"
" DistributionInZ: [Linear]\n" +
std::string{
with_boundary_conditions
? boundary_conditions_string(periodic_in_z)
: " IsPeriodicInZ: " +
std::string{periodic_in_z ? "true" : "false"} +
"\n"}};
const std::string opt_string{
"Cylinder:\n"
" InnerRadius: 1.0\n"
" OuterRadius: 2.0\n"
" LowerZBound: -2.5\n"
" UpperZBound: 5.0\n"
" InitialRefinement: 2\n"
" InitialGridPoints: [4,4,3]\n"
" UseEquiangularMap: " +
std::string{equiangular_map ? "true" : "false"} +
"\n"
" RadialPartitioning: []\n"
" PartitioningInZ: []\n"
" RadialDistribution: [Linear]\n"
" DistributionInZ: [Linear]\n" +
std::string{with_boundary_conditions
? boundary_conditions_string(periodic_in_z)
: " IsPeriodicInZ: " +
std::string{periodic_in_z ? "true" : "false"} +
"\n"}};

const auto cylinder_factory = [&opt_string,
with_boundary_conditions]() {
const auto cylinder_factory =
[&opt_string, with_boundary_conditions = with_boundary_conditions]() {
if (with_boundary_conditions) {
return TestHelpers::test_option_tag<
domain::OptionTags::DomainCreator<3>,
Expand All @@ -333,86 +332,81 @@ void test_cylinder_no_refinement() {
3, domain::creators::Cylinder>>(opt_string);
}
}();
test_cylinder_construction(
dynamic_cast<const creators::Cylinder&>(*cylinder_factory),
inner_radius, outer_radius, lower_z_bound, upper_z_bound,
periodic_in_z, {5, grid_points},
{5, make_array<3>(refinement_level)}, equiangular_map,
with_boundary_conditions);
test_cylinder_construction(
dynamic_cast<const creators::Cylinder&>(*cylinder_factory),
inner_radius, outer_radius, lower_z_bound, upper_z_bound, periodic_in_z,
{5, grid_points}, {5, make_array<3>(refinement_level)}, equiangular_map,
with_boundary_conditions);

if (with_boundary_conditions) {
CHECK_THROWS_WITH(
creators::Cylinder(
inner_radius, outer_radius, lower_z_bound, upper_z_bound,
periodic_in_z ? std::make_unique<PeriodicBc>()
: create_lower_z_boundary_condition(),
periodic_in_z ? std::make_unique<PeriodicBc>()
: create_upper_z_boundary_condition(),
std::make_unique<PeriodicBc>(), refinement_level, grid_points,
equiangular_map, {}, {}, radial_distribution,
distribution_in_z, Options::Context{false, {}, 1, 1}),
Catch::Matchers::Contains(
"A Cylinder can't have periodic boundary conditions in the "
"radial direction."));
CHECK_THROWS_WITH(
creators::Cylinder(inner_radius, outer_radius, lower_z_bound,
upper_z_bound, std::make_unique<PeriodicBc>(),
create_lower_z_boundary_condition(),
create_mantle_boundary_condition(),
refinement_level, grid_points, equiangular_map,
{}, {}, radial_distribution, distribution_in_z,
Options::Context{false, {}, 1, 1}),
Catch::Matchers::Contains(
"Either both lower and upper z-boundary condition must be "
"periodic, or neither."));
CHECK_THROWS_WITH(
creators::Cylinder(
inner_radius, outer_radius, lower_z_bound, upper_z_bound,
create_lower_z_boundary_condition(),
std::make_unique<PeriodicBc>(),
create_mantle_boundary_condition(), refinement_level,
grid_points, equiangular_map, {}, {}, radial_distribution,
distribution_in_z, Options::Context{false, {}, 1, 1}),
Catch::Matchers::Contains(
"Either both lower and upper z-boundary condition must be "
"periodic, or neither."));
CHECK_THROWS_WITH(
creators::Cylinder(inner_radius, outer_radius, lower_z_bound,
upper_z_bound, std::make_unique<NoneBc>(),
create_upper_z_boundary_condition(),
create_mantle_boundary_condition(),
refinement_level, grid_points, equiangular_map,
{}, {}, radial_distribution, distribution_in_z,
Options::Context{false, {}, 1, 1}),
Catch::Matchers::Contains(
"None boundary condition is not supported. If you would like "
"an outflow-type boundary condition, you must use that."));
CHECK_THROWS_WITH(
creators::Cylinder(
inner_radius, outer_radius, lower_z_bound, upper_z_bound,
create_lower_z_boundary_condition(),
std::make_unique<NoneBc>(),
create_mantle_boundary_condition(), refinement_level,
grid_points, equiangular_map, {}, {}, radial_distribution,
distribution_in_z, Options::Context{false, {}, 1, 1}),
Catch::Matchers::Contains(
"None boundary condition is not supported. If you would like "
"an outflow-type boundary condition, you must use that."));
CHECK_THROWS_WITH(
creators::Cylinder(
inner_radius, outer_radius, lower_z_bound, upper_z_bound,
create_lower_z_boundary_condition(),
create_upper_z_boundary_condition(),
std::make_unique<NoneBc>(), refinement_level, grid_points,
equiangular_map, {}, {}, radial_distribution,
distribution_in_z, Options::Context{false, {}, 1, 1}),
Catch::Matchers::Contains(
"None boundary condition is not supported. If you would like "
"an outflow-type boundary condition, you must use that."));
}
} // periodic_in_z
} // equiangular_map
} // with_boundary_conditions
if (with_boundary_conditions) {
CHECK_THROWS_WITH(
creators::Cylinder(
inner_radius, outer_radius, lower_z_bound, upper_z_bound,
periodic_in_z ? std::make_unique<PeriodicBc>()
: create_lower_z_boundary_condition(),
periodic_in_z ? std::make_unique<PeriodicBc>()
: create_upper_z_boundary_condition(),
std::make_unique<PeriodicBc>(), refinement_level, grid_points,
equiangular_map, {}, {}, radial_distribution, distribution_in_z,
Options::Context{false, {}, 1, 1}),
Catch::Matchers::Contains(
"A Cylinder can't have periodic boundary conditions in the "
"radial direction."));
CHECK_THROWS_WITH(
creators::Cylinder(inner_radius, outer_radius, lower_z_bound,
upper_z_bound, std::make_unique<PeriodicBc>(),
create_lower_z_boundary_condition(),
create_mantle_boundary_condition(),
refinement_level, grid_points, equiangular_map, {},
{}, radial_distribution, distribution_in_z,
Options::Context{false, {}, 1, 1}),
Catch::Matchers::Contains(
"Either both lower and upper z-boundary condition must be "
"periodic, or neither."));
CHECK_THROWS_WITH(
creators::Cylinder(inner_radius, outer_radius, lower_z_bound,
upper_z_bound, create_lower_z_boundary_condition(),
std::make_unique<PeriodicBc>(),
create_mantle_boundary_condition(),
refinement_level, grid_points, equiangular_map, {},
{}, radial_distribution, distribution_in_z,
Options::Context{false, {}, 1, 1}),
Catch::Matchers::Contains(
"Either both lower and upper z-boundary condition must be "
"periodic, or neither."));
CHECK_THROWS_WITH(
creators::Cylinder(
inner_radius, outer_radius, lower_z_bound, upper_z_bound,
std::make_unique<NoneBc>(), create_upper_z_boundary_condition(),
create_mantle_boundary_condition(), refinement_level, grid_points,
equiangular_map, {}, {}, radial_distribution, distribution_in_z,
Options::Context{false, {}, 1, 1}),
Catch::Matchers::Contains(
"None boundary condition is not supported. If you would like "
"an outflow-type boundary condition, you must use that."));
CHECK_THROWS_WITH(
creators::Cylinder(
inner_radius, outer_radius, lower_z_bound, upper_z_bound,
create_lower_z_boundary_condition(), std::make_unique<NoneBc>(),
create_mantle_boundary_condition(), refinement_level, grid_points,
equiangular_map, {}, {}, radial_distribution, distribution_in_z,
Options::Context{false, {}, 1, 1}),
Catch::Matchers::Contains(
"None boundary condition is not supported. If you would like "
"an outflow-type boundary condition, you must use that."));
CHECK_THROWS_WITH(
creators::Cylinder(inner_radius, outer_radius, lower_z_bound,
upper_z_bound, create_lower_z_boundary_condition(),
create_upper_z_boundary_condition(),
std::make_unique<NoneBc>(), refinement_level,
grid_points, equiangular_map, {}, {},
radial_distribution, distribution_in_z,
Options::Context{false, {}, 1, 1}),
Catch::Matchers::Contains(
"None boundary condition is not supported. If you would like "
"an outflow-type boundary condition, you must use that."));
}
}
}

void test_refined_cylinder_boundaries(
Expand Down
Loading