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