Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <array>
7 : #include <cstddef>
8 : #include <string>
9 : #include <unordered_map>
10 : #include <unordered_set>
11 : #include <vector>
12 :
13 : #include "Utilities/MakeArray.hpp"
14 :
15 : namespace domain {
16 :
17 : namespace ExpandOverBlocks_detail {
18 : template <typename T, typename U, typename = std::void_t<>>
19 : struct is_value_type {
20 : static constexpr bool value = false;
21 : };
22 :
23 : template <typename T, typename U>
24 : struct is_value_type<T, U, std::void_t<typename T::value_type>> {
25 : static constexpr bool value = std::is_same_v<U, typename T::value_type>;
26 : };
27 : } // namespace ExpandOverBlocks_detail
28 :
29 : /*!
30 : * \brief Produce a std::vector<T> over all blocks of the domain
31 : *
32 : * This class is useful to option-create values for e.g. the initial refinement
33 : * level or initial number of grid points for domain creators. It can be used
34 : * with `std::visit` and a `std::variant` with (a subset of) these types:
35 : *
36 : * - `T`: Repeat the given value over all blocks (homogeneous).
37 : * - `std::vector<T>`: Only check if the size matches the
38 : * number of blocks, throwing a `std::length_error` if it doesn't.
39 : * - `std::unordered_map<std::string, T>`: Map block names, or
40 : * names of block groups, to values. The map must cover all blocks once the
41 : * groups are expanded. To use this option you must pass the list of block
42 : * names and groups to the constructor.
43 : * - `T::value_type`: Repeat the given value over all blocks and dimensions
44 : * (isotropic and homogeneous). Only works if `T` is a `std::array`. For
45 : * example, if `T` is `std::array<size_t, 3>`, this will produce a
46 : * `std::vector<std::array<size_t, 3>>` with the same value repeated
47 : * `num_blocks x 3` times.
48 : *
49 : * If `T` is a `std::unique_ptr`, the class will clone the value for each block
50 : * using `T::get_clone()`.
51 : *
52 : * Note that the call-operators `throw` when they encounter errors, such as
53 : * mismatches in the number of blocks. The exceptions can be used to output
54 : * user-facing error messages in an option-parsing context.
55 : *
56 : * Here's an example for using this class:
57 : *
58 : * \snippet Test_ExpandOverBlocks.cpp expand_over_blocks_example
59 : *
60 : * Here's an example using block names and groups:
61 : *
62 : * \snippet Test_ExpandOverBlocks.cpp expand_over_blocks_named_example
63 : *
64 : * \tparam T The type distributed over the domain
65 : */
66 : template <typename T>
67 1 : struct ExpandOverBlocks {
68 0 : ExpandOverBlocks(size_t num_blocks);
69 0 : ExpandOverBlocks(
70 : std::vector<std::string> block_names,
71 : std::unordered_map<std::string, std::unordered_set<std::string>>
72 : block_groups = {});
73 :
74 : /// Repeat over all blocks (homogeneous)
75 1 : std::vector<T> operator()(const T& value) const;
76 :
77 : /// Only check if the size matches the number of blocks, throwing a
78 : /// `std::length_error` if it doesn't
79 1 : std::vector<T> operator()(const std::vector<T>& value) const;
80 :
81 : /// Map block names, or names of block groups, to values. The map must cover
82 : /// all blocks once the groups are expanded. To use this option you must pass
83 : /// the list of block names and groups to the constructor. Here's an example:
84 : ///
85 : /// \snippet Test_ExpandOverBlocks.cpp expand_over_blocks_named_example
86 1 : std::vector<T> operator()(
87 : const std::unordered_map<std::string, T>& value) const;
88 :
89 : /// Repeat over all blocks and dimensions (isotropic and homogeneous)
90 : template <
91 : typename U,
92 : Requires<ExpandOverBlocks_detail::is_value_type<T, U>::value> = nullptr>
93 1 : std::vector<T> operator()(const U& value) const {
94 : return {num_blocks_, make_array<std::tuple_size_v<T>>(value)};
95 : }
96 :
97 : private:
98 0 : size_t num_blocks_;
99 0 : std::vector<std::string> block_names_;
100 : std::unordered_map<std::string, std::unordered_set<std::string>>
101 0 : block_groups_;
102 : };
103 :
104 : } // namespace domain
|