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

Support a different elastic material in each block #5737

Merged
merged 7 commits into from
Mar 1, 2024
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
4 changes: 2 additions & 2 deletions src/Domain/Creators/BinaryCompactObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,8 @@ BinaryCompactObject::BinaryCompactObject(
<< number_of_blocks_ << ").");

// Expand initial refinement and number of grid points over all blocks
const ExpandOverBlocks<size_t, 3> expand_over_blocks{block_names_,
block_groups_};
const ExpandOverBlocks<std::array<size_t, 3>> expand_over_blocks{
block_names_, block_groups_};

try {
initial_refinement_ = std::visit(expand_over_blocks, initial_refinement);
Expand Down
61 changes: 61 additions & 0 deletions src/Domain/Creators/BlockGroups.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Distributed under the MIT License.
// See LICENSE.txt for details.

#include "Domain/Creators/BlockGroups.hpp"

#include <exception>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "Utilities/ErrorHandling/Error.hpp"
#include "Utilities/StdHelpers.hpp"

namespace domain {

bool block_is_in_group(
const std::string& block_name, const std::string& block_or_group_name,
const std::unordered_map<std::string, std::unordered_set<std::string>>&
block_groups) {
if (block_name == block_or_group_name) {
return true;
}
const auto block_group_it = block_groups.find(block_or_group_name);
return block_group_it != block_groups.end() and
block_group_it->second.count(block_name) == 1;
}

std::unordered_set<std::string> expand_block_groups_to_block_names(
const std::vector<std::string>& block_or_group_names,
const std::vector<std::string>& all_block_names,
const std::unordered_map<std::string, std::unordered_set<std::string>>&
block_groups) {
// Use an unordered_set to elide duplicates
std::unordered_set<std::string> expanded_block_names;
for (const auto& block_or_group_name : block_or_group_names) {
if (const auto block_group_it = block_groups.find(block_or_group_name);
block_group_it != block_groups.end()) {
expanded_block_names.insert(block_group_it->second.begin(),
block_group_it->second.end());
} else if (const auto block_name_it =
std::find(all_block_names.begin(), all_block_names.end(),
block_or_group_name);
block_name_it != all_block_names.end()) {
expanded_block_names.insert(*block_name_it);
} else {
using ::operator<<;
ERROR_AS(
"The block or group '"
<< block_or_group_name
<< "' is not one of the block names or groups of the domain. "
"The known block groups are "
<< keys_of(block_groups) << " and the known block names are "
<< all_block_names,
std::invalid_argument);
}
}
return expanded_block_names;
}

} // namespace domain
45 changes: 45 additions & 0 deletions src/Domain/Creators/BlockGroups.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Distributed under the MIT License.
// See LICENSE.txt for details.

/// \file
/// Utilities to work with block names and groups

#pragma once

#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

namespace domain {

/*!
* \brief Check if a block is in the given group
*
* \param block_name The name of the block to check
* \param block_or_group_name The group name we're testing. Returns true if
* the block is in this group. This can also be the name of the block itself.
* \param block_groups All block groups.
*/
bool block_is_in_group(
const std::string& block_name, const std::string& block_or_group_name,
const std::unordered_map<std::string, std::unordered_set<std::string>>&
block_groups);

/*!
* \brief Expand a list of block or group names into a list of block names
*
* \param block_or_group_names Block or group names to expand
* \param all_block_names All block names in the domain
* \param block_groups Block groups used to expand the names
* \return std::unordered_set<std::string> List of block names that appear in
* \p all_block_names. If one of the input names was a group, then all block
* names from that group are included. Overlaps between groups are allowed.
*/
std::unordered_set<std::string> expand_block_groups_to_block_names(
const std::vector<std::string>& block_or_group_names,
const std::vector<std::string>& all_block_names,
const std::unordered_map<std::string, std::unordered_set<std::string>>&
block_groups);

} // namespace domain
40 changes: 18 additions & 22 deletions src/Domain/Creators/Brick.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,18 @@ struct Inertial;

namespace domain::creators {
Brick::Brick(
typename LowerBound::type lower_xyz, typename UpperBound::type upper_xyz,
typename InitialRefinement::type initial_refinement_level_xyz,
typename InitialGridPoints::type initial_number_of_grid_points_in_xyz,
typename IsPeriodicIn::type is_periodic_in_xyz,
std::array<double, 3> lower_xyz, std::array<double, 3> upper_xyz,
std::array<size_t, 3> initial_refinement_level_xyz,
std::array<size_t, 3> initial_number_of_grid_points_in_xyz,
std::array<bool, 3> is_periodic_in_xyz,
std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>
time_dependence)
// clang-tidy: trivially copyable
: lower_xyz_(std::move(lower_xyz)), // NOLINT
upper_xyz_(std::move(upper_xyz)), // NOLINT
is_periodic_in_xyz_(std::move(is_periodic_in_xyz)), // NOLINT
initial_refinement_level_xyz_( // NOLINT
std::move(initial_refinement_level_xyz)), // NOLINT
initial_number_of_grid_points_in_xyz_( // NOLINT
std::move(initial_number_of_grid_points_in_xyz)), // NOLINT
: lower_xyz_(lower_xyz),
upper_xyz_(upper_xyz),
is_periodic_in_xyz_(is_periodic_in_xyz),
initial_refinement_level_xyz_(initial_refinement_level_xyz),
initial_number_of_grid_points_in_xyz_(
initial_number_of_grid_points_in_xyz),
time_dependence_(std::move(time_dependence)),
boundary_condition_in_lower_x_(nullptr),
boundary_condition_in_upper_x_(nullptr),
Expand All @@ -58,9 +56,9 @@ Brick::Brick(
}

Brick::Brick(
typename LowerBound::type lower_xyz, typename UpperBound::type upper_xyz,
typename InitialRefinement::type initial_refinement_level_xyz,
typename InitialGridPoints::type initial_number_of_grid_points_in_xyz,
std::array<double, 3> lower_xyz, std::array<double, 3> upper_xyz,
std::array<size_t, 3> initial_refinement_level_xyz,
std::array<size_t, 3> initial_number_of_grid_points_in_xyz,
std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
boundary_condition_in_lower_x,
std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
Expand All @@ -76,14 +74,12 @@ Brick::Brick(
std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>
time_dependence,
const Options::Context& context)
// clang-tidy: trivially copyable
: lower_xyz_(std::move(lower_xyz)), // NOLINT
upper_xyz_(std::move(upper_xyz)), // NOLINT
: lower_xyz_(lower_xyz),
upper_xyz_(upper_xyz),
is_periodic_in_xyz_{{false, false, false}},
initial_refinement_level_xyz_( // NOLINT
std::move(initial_refinement_level_xyz)), // NOLINT
initial_number_of_grid_points_in_xyz_( // NOLINT
std::move(initial_number_of_grid_points_in_xyz)), // NOLINT
initial_refinement_level_xyz_(initial_refinement_level_xyz),
initial_number_of_grid_points_in_xyz_(
initial_number_of_grid_points_in_xyz),
time_dependence_(std::move(time_dependence)),
boundary_condition_in_lower_x_(std::move(boundary_condition_in_lower_x)),
boundary_condition_in_upper_x_(std::move(boundary_condition_in_upper_x)),
Expand Down
29 changes: 13 additions & 16 deletions src/Domain/Creators/Brick.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,18 +152,16 @@ class Brick : public DomainCreator<3> {

static constexpr Options::String help{"Creates a 3D brick."};

Brick(typename LowerBound::type lower_xyz,
typename UpperBound::type upper_xyz,
typename InitialRefinement::type initial_refinement_level_xyz,
typename InitialGridPoints::type initial_number_of_grid_points_in_xyz,
typename IsPeriodicIn::type is_periodic_in_xyz,
Brick(std::array<double, 3> lower_xyz, std::array<double, 3> upper_xyz,
std::array<size_t, 3> initial_refinement_level_xyz,
std::array<size_t, 3> initial_number_of_grid_points_in_xyz,
std::array<bool, 3> is_periodic_in_xyz,
std::unique_ptr<domain::creators::time_dependence::TimeDependence<3>>
time_dependence = nullptr);

Brick(typename LowerBound::type lower_xyz,
typename UpperBound::type upper_xyz,
typename InitialRefinement::type initial_refinement_level_xyz,
typename InitialGridPoints::type initial_number_of_grid_points_in_xyz,
Brick(std::array<double, 3> lower_xyz, std::array<double, 3> upper_xyz,
std::array<size_t, 3> initial_refinement_level_xyz,
std::array<size_t, 3> initial_number_of_grid_points_in_xyz,
std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
boundary_condition_in_lower_x,
std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
Expand All @@ -181,10 +179,9 @@ class Brick : public DomainCreator<3> {
const Options::Context& context = {});

template <typename BoundaryConditionsBase>
Brick(typename LowerBound::type lower_xyz,
typename UpperBound::type upper_xyz,
typename InitialRefinement::type initial_refinement_level_xyz,
typename InitialGridPoints::type initial_number_of_grid_points_in_xyz,
Brick(std::array<double, 3> lower_xyz, std::array<double, 3> upper_xyz,
std::array<size_t, 3> initial_refinement_level_xyz,
std::array<size_t, 3> initial_number_of_grid_points_in_xyz,
std::variant<std::unique_ptr<BoundaryConditionsBase>,
LowerUpperBoundaryCondition<BoundaryConditionsBase>>
boundary_conditions_in_x,
Expand Down Expand Up @@ -248,9 +245,9 @@ class Brick : public DomainCreator<3> {

template <typename BoundaryConditionsBase>
Brick::Brick(
typename LowerBound::type lower_xyz, typename UpperBound::type upper_xyz,
typename InitialRefinement::type initial_refinement_level_xyz,
typename InitialGridPoints::type initial_number_of_grid_points_in_xyz,
std::array<double, 3> lower_xyz, std::array<double, 3> upper_xyz,
std::array<size_t, 3> initial_refinement_level_xyz,
std::array<size_t, 3> initial_number_of_grid_points_in_xyz,
std::variant<std::unique_ptr<BoundaryConditionsBase>,
LowerUpperBoundaryCondition<BoundaryConditionsBase>>
boundary_conditions_in_x,
Expand Down
3 changes: 3 additions & 0 deletions src/Domain/Creators/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ spectre_target_sources(
AlignedLattice.cpp
BinaryCompactObject.cpp
BinaryCompactObjectHelpers.cpp
BlockGroups.cpp
Brick.cpp
Cylinder.cpp
CylindricalBinaryCompactObject.cpp
Expand All @@ -34,12 +35,14 @@ spectre_target_headers(
AlignedLattice.hpp
BinaryCompactObject.hpp
BinaryCompactObjectHelpers.hpp
BlockGroups.hpp
Brick.hpp
Cylinder.hpp
CylindricalBinaryCompactObject.hpp
Disk.hpp
DomainCreator.hpp
ExpandOverBlocks.hpp
ExpandOverBlocks.tpp
Factory.hpp
Factory1D.hpp
Factory2D.hpp
Expand Down
4 changes: 2 additions & 2 deletions src/Domain/Creators/Cylinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ Cylinder::Cylinder(
}

// Expand initial refinement and number of grid points over all blocks
const ExpandOverBlocks<size_t, 3> expand_over_blocks{block_names_,
block_groups_};
const ExpandOverBlocks<std::array<size_t, 3>> expand_over_blocks{
block_names_, block_groups_};
try {
initial_refinement_ = std::visit(expand_over_blocks, initial_refinement);
} catch (const std::exception& error) {
Expand Down
4 changes: 2 additions & 2 deletions src/Domain/Creators/CylindricalBinaryCompactObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,8 @@ CylindricalBinaryCompactObject::CylindricalBinaryCompactObject(
}

// Expand initial refinement over all blocks
const ExpandOverBlocks<size_t, 3> expand_over_blocks{block_names_,
block_groups_};
const ExpandOverBlocks<std::array<size_t, 3>> expand_over_blocks{
block_names_, block_groups_};
try {
initial_refinement_ = std::visit(expand_over_blocks, initial_refinement);
} catch (const std::exception& error) {
Expand Down
102 changes: 4 additions & 98 deletions src/Domain/Creators/ExpandOverBlocks.cpp
Original file line number Diff line number Diff line change
@@ -1,109 +1,15 @@
// Distributed under the MIT License.
// See LICENSE.txt for details.

#include "Domain/Creators/ExpandOverBlocks.hpp"
#include "Domain/Creators/ExpandOverBlocks.tpp"

#include <array>
#include <boost/algorithm/string/join.hpp>
#include <cstddef>
#include <exception>
#include <string>
#include <vector>

#include "Utilities/ErrorHandling/Assert.hpp"
#include "Utilities/GenerateInstantiations.hpp"
#include "Utilities/MakeArray.hpp"

namespace domain {

template <typename T, size_t Dim>
ExpandOverBlocks<T, Dim>::ExpandOverBlocks(size_t num_blocks)
: num_blocks_(num_blocks) {}

template <typename T, size_t Dim>
ExpandOverBlocks<T, Dim>::ExpandOverBlocks(
std::vector<std::string> block_names,
std::unordered_map<std::string, std::unordered_set<std::string>>
block_groups)
: num_blocks_(block_names.size()),
block_names_(std::move(block_names)),
block_groups_(std::move(block_groups)) {}

template <typename T, size_t Dim>
std::vector<std::array<T, Dim>> ExpandOverBlocks<T, Dim>::operator()(
const T& value) const {
return {num_blocks_, make_array<Dim>(value)};
}

template <typename T, size_t Dim>
std::vector<std::array<T, Dim>> ExpandOverBlocks<T, Dim>::operator()(
const std::array<T, Dim>& value) const {
return {num_blocks_, value};
}

template <typename T, size_t Dim>
std::vector<std::array<T, Dim>> ExpandOverBlocks<T, Dim>::operator()(
const std::vector<std::array<T, Dim>> value) const {
if (value.size() != num_blocks_) {
throw std::length_error{"You supplied " + std::to_string(value.size()) +
" values, but the domain creator has " +
std::to_string(num_blocks_) + " blocks."};
}
return value;
}

template <typename T, size_t Dim>
std::vector<std::array<T, Dim>> ExpandOverBlocks<T, Dim>::operator()(
const std::unordered_map<std::string, std::array<T, Dim>>& value) const {
ASSERT(num_blocks_ == block_names_.size(),
"Construct 'ExpandOverBlocks' with block names to use the "
"map-over-block-names feature.");
// Expand group names
auto value_per_block = value;
for (const auto& [name, block_value] : value) {
const auto found_group = block_groups_.find(name);
if (found_group != block_groups_.end()) {
for (const auto& expanded_name : found_group->second) {
if (value_per_block.count(expanded_name) == 0) {
value_per_block[expanded_name] = block_value;
} else {
throw std::invalid_argument{
"Duplicate block name '" + expanded_name +
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
"' (expanded from '" + name + "')."};
}
}
value_per_block.erase(name);
}
}
if (value_per_block.size() != num_blocks_) {
throw std::length_error{
"You supplied " + std::to_string(value_per_block.size()) +
" values, but the domain creator has " + std::to_string(num_blocks_) +
" blocks: " + boost::algorithm::join(block_names_, ", ")};
}
std::vector<std::array<T, Dim>> result{};
for (const auto& block_name : block_names_) {
const auto found_value = value_per_block.find(block_name);
if (found_value != value_per_block.end()) {
result.push_back(found_value->second);
} else {
throw std::out_of_range{"Value for block '" + block_name +
"' is missing. Did you misspell its name?"};
}
}
return result;
}

#define DTYPE(data) BOOST_PP_TUPLE_ELEM(0, data)
#define DIM(data) BOOST_PP_TUPLE_ELEM(1, data)
#define INSTANTIATE(_, data) \
template class ExpandOverBlocks<DTYPE(data), DIM(data)>;

GENERATE_INSTANTIATIONS(INSTANTIATE, (size_t), (1, 2, 3))

#undef DIM
#undef DTYPE
#undef INSTANTIATE
template class ExpandOverBlocks<std::array<size_t, 1>>;
template class ExpandOverBlocks<std::array<size_t, 2>>;
template class ExpandOverBlocks<std::array<size_t, 3>>;

} // namespace domain
Loading
Loading