Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 13 additions & 15 deletions src/ControlSystem/ExpirationTimes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ template <size_t Dim, typename... OptionHolders>
std::unordered_map<std::string, double> initial_expiration_times(
const double initial_time, const int measurements_per_update,
const std::unique_ptr<::DomainCreator<Dim>>& domain_creator,
const OptionHolders&... option_holders) {
const std::optional<OptionHolders>&... option_holders) {
std::unordered_map<std::string, double> initial_expiration_times{};

using control_systems = tmpl::list<typename OptionHolders::control_system...>;
Expand All @@ -149,31 +149,29 @@ std::unordered_map<std::string, double> initial_expiration_times(
[&initial_time, &measurements_per_update, &domain_creator, &map_of_names,
&combined_expiration_times,
&infinite_expiration_times](const auto& option_holder) {
const std::string& control_system_name =
std::decay_t<decltype(option_holder)>::control_system::name();
const std::string& control_system_name = std::decay_t<
decltype(option_holder)>::value_type::control_system::name();
const std::string& combined_name = map_of_names[control_system_name];

auto tuner = option_holder.tuner;
// If not active, leave the expiration time as infinity
if (not option_holder.has_value()) {
infinite_expiration_times.insert(control_system_name);
return;
}

auto tuner = option_holder->tuner;
Tags::detail::initialize_tuner(make_not_null(&tuner), domain_creator,
initial_time, control_system_name);

const auto& controller = option_holder.controller;
const auto& controller = option_holder->controller;
const DataVector measurement_timescales =
calculate_measurement_timescales(controller, tuner,
measurements_per_update);
const double min_measurement_timescale = min(measurement_timescales);

double initial_expiration_time = function_of_time_expiration_time(
const double initial_expiration_time = function_of_time_expiration_time(
initial_time, DataVector{1, 0.0},
DataVector{1, min_measurement_timescale}, measurements_per_update);
initial_expiration_time = option_holder.is_active
? initial_expiration_time
: std::numeric_limits<double>::infinity();

if (initial_expiration_time ==
std::numeric_limits<double>::infinity()) {
infinite_expiration_times.insert(control_system_name);
}

combined_expiration_times[combined_name] = std::min(
combined_expiration_times[combined_name], initial_expiration_time);
Expand All @@ -185,7 +183,7 @@ std::unordered_map<std::string, double> initial_expiration_times(
// time
for (const auto& [control_system_name, combined_name] : map_of_names) {
initial_expiration_times[control_system_name] =
infinite_expiration_times.count(control_system_name) == 1
infinite_expiration_times.contains(control_system_name)
? std::numeric_limits<double>::infinity()
: combined_expiration_times[combined_name];
}
Expand Down
21 changes: 18 additions & 3 deletions src/ControlSystem/Tags/FunctionsOfTimeInitialize.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "Domain/Creators/Tags/FunctionsOfTime.hpp"
#include "Domain/FunctionsOfTime/FunctionOfTime.hpp"
#include "Domain/FunctionsOfTime/Tags.hpp"
#include "Options/Auto.hpp"
#include "Time/OptionTags/InitialTime.hpp"
#include "Time/OptionTags/InitialTimeStep.hpp"
#include "Utilities/TMPL.hpp"
Expand Down Expand Up @@ -74,14 +75,27 @@ struct FunctionsOfTimeInitialize : domain::Tags::FunctionsOfTime,
tmpl::list<>>,
domain::OptionTags::DomainCreator<Metavariables::volume_dim>>;

/// @{
/// This version of create_from_options is used if the metavariables did
/// define control systems
template <typename Metavariables, typename... OptionHolders>
static type create_from_options(
const std::unique_ptr<::DomainCreator<Metavariables::volume_dim>>&
domain_creator,
const int measurements_per_update,
const double initial_time, const OptionHolders&... option_holders) {
const int measurements_per_update, const double initial_time,
const Options::Auto<OptionHolders,
Options::AutoLabel::None>&... option_holders) {
return create_from_options<Metavariables>(
domain_creator, measurements_per_update, initial_time,
static_cast<const std::optional<OptionHolders>&>(option_holders)...);
}

template <typename Metavariables, typename... OptionHolders>
static type create_from_options(
const std::unique_ptr<::DomainCreator<Metavariables::volume_dim>>&
domain_creator,
const int measurements_per_update, const double initial_time,
const std::optional<OptionHolders>&... option_holders) {
const auto initial_expiration_times =
control_system::initial_expiration_times(
initial_time, measurements_per_update, domain_creator,
Expand All @@ -99,12 +113,13 @@ struct FunctionsOfTimeInitialize : domain::Tags::FunctionsOfTime,

return functions_of_time;
}
/// @}

/// This version of create_from_options is used if the metavariables did not
/// define control systems
template <typename Metavariables>
static type create_from_options(
const std::unique_ptr<::DomainCreator<Metavariables::volume_dim>>&
const std::unique_ptr<::DomainCreator<Metavariables::volume_dim>>&
domain_creator) {
return domain_creator->functions_of_time();
}
Expand Down
20 changes: 15 additions & 5 deletions src/ControlSystem/Tags/IsActiveMap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "ControlSystem/Metafunctions.hpp"
#include "ControlSystem/Tags/OptionTags.hpp"
#include "DataStructures/DataBox/Tag.hpp"
#include "Options/Auto.hpp"
#include "Utilities/TMPL.hpp"

/// \cond
Expand All @@ -26,14 +27,14 @@ namespace control_system::Tags {
namespace detail {
template <typename... OptionHolders>
std::unordered_map<std::string, bool> create_is_active_map(
const OptionHolders&... option_holders) {
const std::optional<OptionHolders>&... option_holders) {
std::unordered_map<std::string, bool> result{};

[[maybe_unused]] const auto add_to_result =
[&result](const auto& option_holder) {
using control_system =
typename std::decay_t<decltype(option_holder)>::control_system;
result[control_system::name()] = option_holder.is_active;
using control_system = typename std::decay_t<
decltype(option_holder)>::value_type::control_system;
result[control_system::name()] = option_holder.has_value();
};

EXPAND_PACK_LEFT_TO_RIGHT(add_to_result(option_holders));
Expand Down Expand Up @@ -65,7 +66,16 @@ struct IsActiveMap : db::SimpleTag {
metafunctions::all_control_components<Metavariables>, system<tmpl::_1>>>;

template <typename Metavariables, typename... OptionHolders>
static type create_from_options(const OptionHolders&... option_holders) {
static type create_from_options(
const Options::Auto<OptionHolders,
Options::AutoLabel::None>&... option_holders) {
return create_from_options<Metavariables>(
static_cast<const std::optional<OptionHolders>>(option_holders)...);
}

template <typename Metavariables, typename... OptionHolders>
static type create_from_options(
const std::optional<OptionHolders>&... option_holders) {
return detail::create_is_active_map(option_holders...);
}
};
Expand Down
47 changes: 32 additions & 15 deletions src/ControlSystem/Tags/MeasurementTimescales.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "Domain/Creators/OptionTags.hpp"
#include "Domain/FunctionsOfTime/FunctionOfTime.hpp"
#include "Domain/FunctionsOfTime/PiecewisePolynomial.hpp"
#include "Options/Auto.hpp"
#include "Time/OptionTags/InitialTime.hpp"
#include "Time/OptionTags/InitialTimeStep.hpp"
#include "Utilities/ErrorHandling/Error.hpp"
Expand Down Expand Up @@ -83,7 +84,21 @@ struct MeasurementTimescales : db::SimpleTag {
const std::unique_ptr<::DomainCreator<Metavariables::volume_dim>>&
domain_creator,
const double initial_time, const double initial_time_step,
const OptionHolders&... option_holders) {
const Options::Auto<OptionHolders,
Options::AutoLabel::None>&... option_holders) {
return create_from_options<Metavariables>(
measurements_per_update, domain_creator, initial_time,
initial_time_step,
static_cast<std::optional<OptionHolders>>(option_holders)...);
}

template <typename Metavariables, typename... OptionHolders>
static type create_from_options(
const int measurements_per_update,
const std::unique_ptr<::DomainCreator<Metavariables::volume_dim>>&
domain_creator,
const double initial_time, const double initial_time_step,
const std::optional<OptionHolders>&... option_holders) {
std::unordered_map<std::string,
std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>
timescales{};
Expand Down Expand Up @@ -121,25 +136,27 @@ struct MeasurementTimescales : db::SimpleTag {
"evolutions.");
}

const std::string& control_system_name =
std::decay_t<decltype(option_holder)>::control_system::name();
const std::string& control_system_name = std::decay_t<
decltype(option_holder)>::value_type::control_system::name();
const std::string& combined_name = map_of_names[control_system_name];

auto tuner = option_holder.tuner;
::control_system::Tags::detail::initialize_tuner(
make_not_null(&tuner), domain_creator, initial_time,
control_system_name);
// If the control system isn't active, set measurement timescale and
// expiration time to be infinity.
double min_measurement_timescale =
std::numeric_limits<double>::infinity();

const auto& controller = option_holder.controller;
DataVector measurement_timescales = calculate_measurement_timescales(
controller, tuner, measurements_per_update);
if (option_holder.has_value()) {
auto tuner = option_holder->tuner;
::control_system::Tags::detail::initialize_tuner(
make_not_null(&tuner), domain_creator, initial_time,
control_system_name);

double min_measurement_timescale = min(measurement_timescales);
const auto& controller = option_holder->controller;
DataVector measurement_timescales =
calculate_measurement_timescales(controller, tuner,
measurements_per_update);

// If the control system isn't active, set measurement timescale and
// expiration time to be infinity.
if (not option_holder.is_active) {
min_measurement_timescale = std::numeric_limits<double>::infinity();
min_measurement_timescale = min(measurement_timescales);
}

min_measurement_timescales[combined_name] =
Expand Down
25 changes: 10 additions & 15 deletions src/ControlSystem/Tags/OptionTags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "ControlSystem/Protocols/ControlSystem.hpp"
#include "ControlSystem/TimescaleTuner.hpp"
#include "IO/Logging/Verbosity.hpp"
#include "Options/Auto.hpp"
#include "Options/String.hpp"
#include "Utilities/ProtocolHelpers.hpp"
#include "Utilities/TMPL.hpp"
Expand All @@ -23,6 +24,8 @@ namespace control_system {
/// This struct collects all the options for a given control system during
/// option parsing. Then during initialization, the options can be retrieved via
/// their public member names and assigned to their corresponding DataBox tags.
///
/// This class should only be used if a control system is active.
template <typename ControlSystem>
struct OptionHolder {
private:
Expand All @@ -34,13 +37,6 @@ struct OptionHolder {
ControlSystem, control_system::protocols::ControlSystem>);
using control_system = ControlSystem;
static constexpr size_t deriv_order = control_system::deriv_order;
struct IsActive {
using type = bool;
static constexpr Options::String help = {
"Whether the control system is actually active. If it isn't active, no "
"measurements (horizon finds) will be done and the functions of time "
"will never expire."};
};

struct Averager {
using type = ::Averager<deriv_order - 1>;
Expand Down Expand Up @@ -71,16 +67,14 @@ struct OptionHolder {
};

using options =
tmpl::list<IsActive, Averager, Controller, TimescaleTuner, ControlError>;
tmpl::list<Averager, Controller, TimescaleTuner, ControlError>;
static constexpr Options::String help = {"Options for a control system."};

OptionHolder(const bool input_is_active,
::Averager<deriv_order - 1> input_averager,
OptionHolder(::Averager<deriv_order - 1> input_averager,
::Controller<deriv_order> input_controller,
::TimescaleTuner<not is_size> input_tuner,
typename ControlSystem::control_error input_control_error)
: is_active(input_is_active),
averager(std::move(input_averager)),
: averager(std::move(input_averager)),
controller(std::move(input_controller)),
tuner(std::move(input_tuner)),
control_error(std::move(input_control_error)) {}
Expand All @@ -94,7 +88,6 @@ struct OptionHolder {

// NOLINTNEXTLINE(google-runtime-references)
void pup(PUP::er& p) {
p | is_active;
p | averager;
p | controller;
p | tuner;
Expand All @@ -103,7 +96,6 @@ struct OptionHolder {

// These members are specifically made public for easy access during
// initialization
bool is_active{true};
::Averager<deriv_order - 1> averager{};
::Controller<deriv_order> controller{};
::TimescaleTuner<not is_size> tuner{};
Expand All @@ -127,9 +119,12 @@ struct ControlSystemGroup {
/// Option tag for each individual control system. The name of this option is
/// the name of the \p ControlSystem struct it is templated on. This way all
/// control systems will have a unique name.
///
/// \details If `None` is specified, this control system is not active.
template <typename ControlSystem>
struct ControlSystemInputs {
using type = control_system::OptionHolder<ControlSystem>;
using type = Options::Auto<control_system::OptionHolder<ControlSystem>,
Options::AutoLabel::None>;
static constexpr Options::String help{"Options for a control system."};
static std::string name() { return ControlSystem::name(); }
using group = ControlSystemGroup;
Expand Down
Loading
Loading