Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <cstddef> 7 : #include <functional> 8 : #include <optional> 9 : #include <pup.h> 10 : #include <pup_stl.h> 11 : #include <random> 12 : #include <string> 13 : #include <tuple> 14 : #include <utility> 15 : 16 : #include "DataStructures/DataBox/DataBox.hpp" 17 : #include "DataStructures/Variables.hpp" 18 : #include "DataStructures/VariablesTag.hpp" 19 : #include "Domain/Structure/ElementId.hpp" 20 : #include "Options/Auto.hpp" 21 : #include "Options/String.hpp" 22 : #include "Parallel/AlgorithmExecution.hpp" 23 : #include "Utilities/Gsl.hpp" 24 : #include "Utilities/PrettyType.hpp" 25 : #include "Utilities/Serialization/PupStlCpp17.hpp" 26 : #include "Utilities/TMPL.hpp" 27 : 28 : /// \cond 29 : namespace Parallel { 30 : template <typename Metavariables> 31 : struct GlobalCache; 32 : } // namespace Parallel 33 : namespace tuples { 34 : template <typename... Tags> 35 : struct TaggedTuple; 36 : } // namespace tuples 37 : /// \endcond 38 : 39 : namespace Actions { 40 : 41 : /*! 42 : * \brief Optionally add random noise to the initial guess. 43 : * 44 : * Use this action to add random noise to variables. The random noise can be 45 : * toggled and is configurable with input-file options. Adding random noise to 46 : * fields can be useful to test the convergence and stability. 47 : */ 48 : template <typename VariablesTag, typename Label> 49 1 : struct RandomizeVariables { 50 : public: 51 : // Bundle the options so they can be placed in Options::Auto 52 0 : struct RandomParameters { 53 0 : struct Amplitude { 54 0 : using type = double; 55 0 : static constexpr Options::String help = "Amplitude of the uniform noise."; 56 : }; 57 0 : struct Seed { 58 0 : using type = Options::Auto<size_t>; 59 0 : static constexpr Options::String help = 60 : "Random seed for the noise generator."; 61 : }; 62 0 : using options = tmpl::list<Amplitude, Seed>; 63 0 : static constexpr Options::String help = "Parameters for the uniform noise."; 64 0 : void pup(PUP::er& p) { 65 : p | amplitude; 66 : p | seed; 67 : } 68 0 : double amplitude; 69 0 : std::optional<size_t> seed; 70 : }; 71 : 72 0 : struct RandomParametersOptionTag { 73 0 : static std::string name() { return pretty_type::name<Label>(); } 74 0 : using type = Options::Auto<RandomParameters, Options::AutoLabel::None>; 75 0 : static constexpr Options::String help = 76 : "Add uniform random noise to variables."; 77 : }; 78 : 79 0 : struct RandomParametersTag : db::SimpleTag { 80 0 : using type = std::optional<RandomParameters>; 81 0 : using option_tags = tmpl::list<RandomParametersOptionTag>; 82 0 : static constexpr bool pass_metavariables = false; 83 0 : static type create_from_options(const type& value) { return value; } 84 : }; 85 : 86 0 : using const_global_cache_tags = tmpl::list<RandomParametersTag>; 87 : 88 : template <typename DbTagsList, typename... InboxTags, typename Metavariables, 89 : size_t Dim, typename ActionList, typename ParallelComponent> 90 0 : static Parallel::iterable_action_return_t apply( 91 : db::DataBox<DbTagsList>& box, 92 : const tuples::TaggedTuple<InboxTags...>& /*inboxes*/, 93 : const Parallel::GlobalCache<Metavariables>& /*cache*/, 94 : const ElementId<Dim>& element_id, const ActionList /*meta*/, 95 : const ParallelComponent* const /*meta*/) { 96 : // Retrieve the options 97 : const std::optional<RandomParameters>& params = 98 : db::get<RandomParametersTag>(box); 99 : if (not params.has_value()) { 100 : return {Parallel::AlgorithmExecution::Continue, std::nullopt}; 101 : } 102 : const auto& [amplitude, seed] = params.value(); 103 : // Seed a random generator. Include the element ID in the seed so the data 104 : // is different on each element. 105 : std::seed_seq seeds{std::hash<ElementId<Dim>>{}(element_id), 106 : seed.value_or(std::random_device{}())}; 107 : std::mt19937 generator{seeds}; 108 : // Set up the random distribution 109 : std::uniform_real_distribution<> dist(-amplitude, amplitude); 110 : // Add noise to the fields 111 : db::mutate<VariablesTag>( 112 : [&generator, &dist](const auto fields) { 113 : for (size_t i = 0; i < fields->size(); ++i) { 114 : fields->data()[i] += dist(generator); 115 : } 116 : }, 117 : make_not_null(&box)); 118 : return {Parallel::AlgorithmExecution::Continue, std::nullopt}; 119 : } 120 : }; 121 : 122 : } // namespace Actions