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
|