Skip to content

Commit

Permalink
Allow random hp AMR for testing
Browse files Browse the repository at this point in the history
Support triggering any of the AMR flags with a specified probability, rather than
only h-refinement. Simplifies the reasoning of the AMR criterion
and gives more control over the types of refinement.
Removes the maximum refinement level, because it can be
set globally with an upcoming AMR policy.
  • Loading branch information
nilsvu committed Feb 16, 2024
1 parent 1e66fc9 commit 8879930
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 57 deletions.
31 changes: 14 additions & 17 deletions src/ParallelAlgorithms/Amr/Criteria/Random.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,39 @@

#include "ParallelAlgorithms/Amr/Criteria/Random.hpp"

#include <cstddef>
#include <map>
#include <random>

#include "Domain/Amr/Flag.hpp"

namespace amr::Criteria {
Random::Random(const double do_something_fraction,
const size_t maximum_refinement_level)
: do_something_fraction_(do_something_fraction),
maximum_refinement_level_(maximum_refinement_level) {}
Random::Random(std::map<amr::Flag, double> probability)
: probability_(std::move(probability)) {}

Random::Random(CkMigrateMessage* msg) : Criterion(msg) {}

// NOLINTNEXTLINE(google-runtime-references)
void Random::pup(PUP::er& p) {
Criterion::pup(p);
p | do_something_fraction_;
p | maximum_refinement_level_;
p | probability_;
}

amr::Flag Random::random_flag(const size_t current_refinement_level) const {
namespace detail {
amr::Flag random_flag(const std::map<amr::Flag, double>& probabilities) {
static std::random_device r;
static const auto seed = r();
static std::mt19937 generator(seed);
static std::uniform_real_distribution<> distribution(0.0, 1.0);

const double random_number = distribution(generator);
if (random_number > do_something_fraction_) {
return amr::Flag::DoNothing;
for (auto it = probabilities.rbegin(); it != probabilities.rend(); ++it) {
const auto& [flag, probability] = *it;
if (distribution(generator) < probability) {
return flag;
}
}
const double join_fraction =
current_refinement_level / static_cast<double>(maximum_refinement_level_);
if (random_number < join_fraction * do_something_fraction_) {
return amr::Flag::Join;
}
return amr::Flag::Split;
return amr::Flag::DoNothing;
}
} // namespace detail

PUP::able::PUP_ID Random::my_PUP_ID = 0; // NOLINT
} // namespace amr::Criteria
68 changes: 28 additions & 40 deletions src/ParallelAlgorithms/Amr/Criteria/Random.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#pragma once

#include <cstddef>
#include <map>
#include <pup.h>

#include "Domain/Amr/Flag.hpp"
Expand All @@ -16,49 +17,39 @@
#include "Utilities/TMPL.hpp"

namespace amr::Criteria {
namespace detail {
amr::Flag random_flag(const std::map<amr::Flag, double>& probabilities);
}

Check failure on line 22 in src/ParallelAlgorithms/Amr/Criteria/Random.hpp

View workflow job for this annotation

GitHub Actions / Clang-tidy (Debug)

namespace 'detail' not terminated with a closing comment

Check failure on line 22 in src/ParallelAlgorithms/Amr/Criteria/Random.hpp

View workflow job for this annotation

GitHub Actions / Clang-tidy (Release)

namespace 'detail' not terminated with a closing comment

/*!
* \brief Randomly h-refine (or coarsen) an Element in each dimension.
*
* \details Let \f$f\f$ be `ChangeRefinementFraction`, \f$L_{max}\f$ be
* `MaximumRefinementLevel`, and \f$L_d\f$ be the current refinement level
* of an Element in a particular dimension. In each dimension, a random
* number \f$r_d \in [0, 1]\f$ is generated. If \f$r_d > f\f$ the refinement
* flag is set to amr::Flags::DoNothing. If \f$r_d < f L_d / L_{max}\f$
* the refinement flag is set to amr::Flags::Join. Otherwise the
* refinement flag is set to amr::Flag::Split.
* \brief Randomly refine (or coarsen) an Element in each dimension.
*
* \note This criterion is primarily useful for testing the mechanics of
* h-refinement
* \details You can specify a probability for each possible `amr::Flag`. The
* probabilities are evaluated in the priority order defined by `amr::Flag`. The
* first one that triggers is used in that dimension. If none of the
* probabilities trigger, then the Element is not refined.
*/
class Random : public Criterion {
public:
/// The fraction of the time random refinement does changes the grid
struct ChangeRefinementFraction {
using type = double;
static constexpr Options::String help = {
"The fraction of the time that random refinement will change the "
"grid."};
static double lower_bound() { return 0.0; }
static double upper_bound() { return 1.0; }
};

/// The maximum allowed refinement level
struct MaximumRefinementLevel {
using type = size_t;
struct Probability {
using type = std::map<amr::Flag, double>;
static constexpr Options::String help = {
"The maximum allowed refinement level."};
static size_t upper_bound() { return ElementId<3>::max_refinement_level; }
"Possible refinement types and their probability. "
"The probabilities are evaluated in order of refinement type "
"priority: first Split, then IncreaseResolution, then "
"DecreaseResolution, then Join. If none of the probabilities "
"trigger, then the Element is not refined."};
};

using options = tmpl::list<ChangeRefinementFraction, MaximumRefinementLevel>;
using options = tmpl::list<Probability>;

static constexpr Options::String help = {
"Randomly h-refine (or coarsen) the grid"};

Random() = default;

Random(const double do_something_fraction,
const size_t maximum_refinement_level);
Random(std::map<amr::Flag, double> probability);

Check failure on line 52 in src/ParallelAlgorithms/Amr/Criteria/Random.hpp

View workflow job for this annotation

GitHub Actions / Clang-tidy (Debug)

single-argument constructors must be marked explicit to avoid unintentional implicit conversions

Check failure on line 52 in src/ParallelAlgorithms/Amr/Criteria/Random.hpp

View workflow job for this annotation

GitHub Actions / Clang-tidy (Release)

single-argument constructors must be marked explicit to avoid unintentional implicit conversions

/// \cond
explicit Random(CkMigrateMessage* msg);
Expand All @@ -70,27 +61,24 @@ class Random : public Criterion {

using argument_tags = tmpl::list<>;

template <typename Metavariables>
template <size_t Dim, typename Metavariables>
auto operator()(Parallel::GlobalCache<Metavariables>& /*cache*/,
const ElementId<Metavariables::volume_dim>& element_id) const;
const ElementId<Dim>& element_id) const;

void pup(PUP::er& p) override;

private:
amr::Flag random_flag(size_t current_refinement_level) const;

double do_something_fraction_{0.0};
size_t maximum_refinement_level_{0};
std::map<amr::Flag, double> probability_{};
};

template <typename Metavariables>
auto Random::operator()(
Parallel::GlobalCache<Metavariables>& /*cache*/,
const ElementId<Metavariables::volume_dim>& element_id) const {
constexpr size_t volume_dim = Metavariables::volume_dim;
auto result = make_array<volume_dim>(amr::Flag::Undefined);
for (size_t d = 0; d < volume_dim; ++d) {
result[d] = random_flag(element_id.segment_ids()[d].refinement_level());
template <size_t Dim, typename Metavariables>
auto Random::operator()(Parallel::GlobalCache<Metavariables>& /*cache*/,
const ElementId<Dim>& /*element_id*/) const {
auto result = make_array<Dim>(amr::Flag::Undefined);
for (size_t d = 0; d < Dim; ++d) {
result[d] = detail::random_flag(probability_);
}
return result;
}
Expand Down

0 comments on commit 8879930

Please sign in to comment.