feat(trigger): added working robust repartitioning trigger system
more work is needed to identify the most robust set of criteria to trigger on but the system is now very easy to exend, probe, and use.
This commit is contained in:
@@ -57,9 +57,9 @@ namespace gridfire {
|
||||
|
||||
// TODO: We should probably sort out how to adjust these from absolute to relative tolerances.
|
||||
QSECacheConfig m_cacheConfig = {
|
||||
1e-3, // Default tolerance for T9
|
||||
1e-1, // Default tolerance for rho
|
||||
1e-3 // Default tolerance for species abundances
|
||||
1e-10, // Default tolerance for T9
|
||||
1e-10, // Default tolerance for rho
|
||||
1e-10 // Default tolerance for species abundances
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -763,7 +763,7 @@ namespace gridfire {
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
std::string toString(DynamicEngine &engine) const;
|
||||
std::string toString(const DynamicEngine &engine) const;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -989,6 +989,11 @@ namespace gridfire {
|
||||
* @brief Species that are treated as algebraic (in QSE) in the QSE groups.
|
||||
*/
|
||||
std::vector<fourdst::atomic::Species> m_algebraic_species;
|
||||
|
||||
/**
|
||||
* @breif Stateful storage of the current algebraic species abundances. This is updated every time the update method is called.
|
||||
*/
|
||||
std::vector<double> m_Y_algebraic;
|
||||
/**
|
||||
* @brief Indices of algebraic species in the full network.
|
||||
*/
|
||||
@@ -1003,7 +1008,6 @@ namespace gridfire {
|
||||
*/
|
||||
std::vector<size_t> m_activeReactionIndices;
|
||||
|
||||
// TODO: Enhance the hashing for the cache to consider not just T and rho but also the current abundance in some careful way that automatically ignores small changes (i.e. network should only be repartitioned sometimes)
|
||||
/**
|
||||
* @brief Cache for QSE abundances based on T9, rho, and Y.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
|
||||
#include "gridfire/trigger/trigger_abstract.h"
|
||||
#include "gridfire/trigger/trigger_result.h"
|
||||
#include "gridfire/solver/strategies/CVODE_solver_strategy.h"
|
||||
#include "fourdst/logging/logging.h"
|
||||
|
||||
#include <string>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
|
||||
namespace gridfire::trigger::solver::CVODE {
|
||||
class SimulationTimeTrigger final : public Trigger<gridfire::solver::CVODESolverStrategy::TimestepContext> {
|
||||
public:
|
||||
explicit SimulationTimeTrigger(double interval);
|
||||
bool check(const gridfire::solver::CVODESolverStrategy::TimestepContext &ctx) const override;
|
||||
void update(const gridfire::solver::CVODESolverStrategy::TimestepContext &ctx) override;
|
||||
void reset() override;
|
||||
|
||||
std::string name() const override;
|
||||
TriggerResult why(const gridfire::solver::CVODESolverStrategy::TimestepContext &ctx) const override;
|
||||
std::string describe() const override;
|
||||
size_t numTriggers() const override;
|
||||
size_t numMisses() const override;
|
||||
private:
|
||||
quill::Logger* m_logger = LogManager::getInstance().getLogger("log");
|
||||
mutable size_t m_hits = 0;
|
||||
mutable size_t m_misses = 0;
|
||||
mutable size_t m_updates = 0;
|
||||
mutable size_t m_resets = 0;
|
||||
|
||||
double m_interval;
|
||||
|
||||
mutable double m_last_trigger_time = 0.0;
|
||||
mutable double m_last_trigger_time_delta = 0.0;
|
||||
};
|
||||
|
||||
class OffDiagonalTrigger final : public Trigger<gridfire::solver::CVODESolverStrategy::TimestepContext> {
|
||||
public:
|
||||
explicit OffDiagonalTrigger(double threshold);
|
||||
bool check(const gridfire::solver::CVODESolverStrategy::TimestepContext &ctx) const override;
|
||||
void update(const gridfire::solver::CVODESolverStrategy::TimestepContext &ctx) override;
|
||||
void reset() override;
|
||||
|
||||
std::string name() const override;
|
||||
TriggerResult why(const gridfire::solver::CVODESolverStrategy::TimestepContext &ctx) const override;
|
||||
std::string describe() const override;
|
||||
size_t numTriggers() const override;
|
||||
size_t numMisses() const override;
|
||||
private:
|
||||
quill::Logger* m_logger = LogManager::getInstance().getLogger("log");
|
||||
mutable size_t m_hits = 0;
|
||||
mutable size_t m_misses = 0;
|
||||
mutable size_t m_updates = 0;
|
||||
mutable size_t m_resets = 0;
|
||||
|
||||
double m_threshold;
|
||||
};
|
||||
|
||||
class TimestepCollapseTrigger final : public Trigger<gridfire::solver::CVODESolverStrategy::TimestepContext> {
|
||||
public:
|
||||
explicit TimestepCollapseTrigger(double threshold, bool relative);
|
||||
explicit TimestepCollapseTrigger(double threshold, bool relative, size_t windowSize);
|
||||
bool check(const gridfire::solver::CVODESolverStrategy::TimestepContext &ctx) const override;
|
||||
void update(const gridfire::solver::CVODESolverStrategy::TimestepContext &ctx) override;
|
||||
void reset() override;
|
||||
|
||||
std::string name() const override;
|
||||
TriggerResult why(const gridfire::solver::CVODESolverStrategy::TimestepContext &ctx) const override;
|
||||
std::string describe() const override;
|
||||
size_t numTriggers() const override;
|
||||
size_t numMisses() const override;
|
||||
private:
|
||||
quill::Logger* m_logger = LogManager::getInstance().getLogger("log");
|
||||
mutable size_t m_hits = 0;
|
||||
mutable size_t m_misses = 0;
|
||||
mutable size_t m_updates = 0;
|
||||
mutable size_t m_resets = 0;
|
||||
|
||||
double m_threshold;
|
||||
bool m_relative;
|
||||
size_t m_windowSize;
|
||||
|
||||
std::deque<double> m_timestep_window;
|
||||
};
|
||||
|
||||
std::unique_ptr<Trigger<gridfire::solver::CVODESolverStrategy::TimestepContext>> makeEnginePartitioningTrigger(
|
||||
const double simulationTimeInterval,
|
||||
const double offDiagonalThreshold,
|
||||
const double timestepGrowthThreshold,
|
||||
const bool timestepGrowthRelative,
|
||||
const size_t timestepGrowthWindowSize
|
||||
);
|
||||
}
|
||||
17
src/include/gridfire/trigger/procedures/trigger_pprint.h
Normal file
17
src/include/gridfire/trigger/procedures/trigger_pprint.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "gridfire/trigger/trigger_result.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace gridfire::trigger {
|
||||
inline void printWhy(const TriggerResult& result, const int indent = 0) {
|
||||
const std::string prefix(indent * 2, ' ');
|
||||
std::cout << prefix << "• [" << (result.value ? "TRUE" : "FALSE")
|
||||
<< "] " << result.name << ": " << result.description << std::endl;
|
||||
|
||||
for (const auto& cause : result.causes) {
|
||||
printWhy(cause, indent + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/include/gridfire/trigger/trigger_abstract.h
Normal file
26
src/include/gridfire/trigger/trigger_abstract.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "gridfire/trigger/trigger_result.h"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace gridfire::trigger {
|
||||
template <typename TriggerContextStruct>
|
||||
class Trigger {
|
||||
public:
|
||||
virtual ~Trigger() = default;
|
||||
|
||||
virtual bool check(const TriggerContextStruct& ctx) const = 0;
|
||||
|
||||
virtual void update(const TriggerContextStruct& ctx) = 0;
|
||||
virtual void reset() = 0;
|
||||
|
||||
virtual std::string name() const = 0;
|
||||
virtual std::string describe() const = 0;
|
||||
virtual TriggerResult why(const TriggerContextStruct& ctx) const = 0;
|
||||
|
||||
virtual size_t numTriggers() const = 0;
|
||||
virtual size_t numMisses() const = 0;
|
||||
};
|
||||
}
|
||||
440
src/include/gridfire/trigger/trigger_logical.h
Normal file
440
src/include/gridfire/trigger/trigger_logical.h
Normal file
@@ -0,0 +1,440 @@
|
||||
#pragma once
|
||||
|
||||
#include "gridfire/trigger/trigger_abstract.h"
|
||||
#include "gridfire/trigger/trigger_result.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace gridfire::trigger {
|
||||
template <typename TriggerContextStruct>
|
||||
class LogicalTrigger : public Trigger<TriggerContextStruct> {};
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
class AndTrigger final : public LogicalTrigger<TriggerContextStruct> {
|
||||
public:
|
||||
AndTrigger(std::unique_ptr<Trigger<TriggerContextStruct>> A, std::unique_ptr<Trigger<TriggerContextStruct>> B);
|
||||
~AndTrigger() override = default;
|
||||
|
||||
bool check(const TriggerContextStruct& ctx) const override;
|
||||
void update(const TriggerContextStruct& ctx) override;
|
||||
void reset() override;
|
||||
std::string name() const override;
|
||||
TriggerResult why(const TriggerContextStruct& ctx) const override;
|
||||
std::string describe() const override;
|
||||
size_t numTriggers() const override;
|
||||
size_t numMisses() const override;
|
||||
private:
|
||||
std::unique_ptr<Trigger<TriggerContextStruct>> m_A;
|
||||
std::unique_ptr<Trigger<TriggerContextStruct>> m_B;
|
||||
|
||||
mutable size_t m_hits = 0;
|
||||
mutable size_t m_misses = 0;
|
||||
mutable size_t m_updates = 0;
|
||||
mutable size_t m_resets = 0;
|
||||
};
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
class OrTrigger final : public LogicalTrigger<TriggerContextStruct> {
|
||||
public:
|
||||
OrTrigger(std::unique_ptr<Trigger<TriggerContextStruct>> A, std::unique_ptr<Trigger<TriggerContextStruct>> B);
|
||||
~OrTrigger() override = default;
|
||||
|
||||
bool check(const TriggerContextStruct& ctx) const override;
|
||||
void update(const TriggerContextStruct& ctx) override;
|
||||
void reset() override;
|
||||
std::string name() const override;
|
||||
TriggerResult why(const TriggerContextStruct& ctx) const override;
|
||||
std::string describe() const override;
|
||||
size_t numTriggers() const override;
|
||||
size_t numMisses() const override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Trigger<TriggerContextStruct>> m_A;
|
||||
std::unique_ptr<Trigger<TriggerContextStruct>> m_B;
|
||||
|
||||
mutable size_t m_hits = 0;
|
||||
mutable size_t m_misses = 0;
|
||||
mutable size_t m_updates = 0;
|
||||
mutable size_t m_resets = 0;
|
||||
};
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
class NotTrigger final : public LogicalTrigger<TriggerContextStruct> {
|
||||
public:
|
||||
explicit NotTrigger(std::unique_ptr<Trigger<TriggerContextStruct>> A);
|
||||
~NotTrigger() override = default;
|
||||
|
||||
bool check(const TriggerContextStruct& ctx) const override;
|
||||
void update(const TriggerContextStruct& ctx) override;
|
||||
void reset() override;
|
||||
|
||||
std::string name() const override;
|
||||
TriggerResult why(const TriggerContextStruct& ctx) const override;
|
||||
std::string describe() const override;
|
||||
size_t numTriggers() const override;
|
||||
size_t numMisses() const override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Trigger<TriggerContextStruct>> m_A;
|
||||
|
||||
mutable size_t m_hits = 0;
|
||||
mutable size_t m_misses = 0;
|
||||
mutable size_t m_updates = 0;
|
||||
mutable size_t m_resets = 0;
|
||||
|
||||
};
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
class EveryNthTrigger final : public LogicalTrigger<TriggerContextStruct> {
|
||||
public:
|
||||
explicit EveryNthTrigger(std::unique_ptr<Trigger<TriggerContextStruct>> A, size_t N);
|
||||
~EveryNthTrigger() override = default;
|
||||
|
||||
bool check(const TriggerContextStruct& ctx) const override;
|
||||
void update(const TriggerContextStruct& ctx) override;
|
||||
void reset() override;
|
||||
|
||||
std::string name() const override;
|
||||
TriggerResult why(const TriggerContextStruct& ctx) const override;
|
||||
std::string describe() const override;
|
||||
size_t numTriggers() const override;
|
||||
size_t numMisses() const override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Trigger<TriggerContextStruct>> m_A;
|
||||
|
||||
size_t m_N;
|
||||
mutable size_t m_counter = 0;
|
||||
mutable size_t m_hits = 0;
|
||||
mutable size_t m_misses = 0;
|
||||
mutable size_t m_updates = 0;
|
||||
mutable size_t m_resets = 0;
|
||||
};
|
||||
|
||||
///////////////////////////////
|
||||
// Templated Implementations //
|
||||
///////////////////////////////
|
||||
|
||||
|
||||
template<typename TriggerContextStruct>
|
||||
AndTrigger<TriggerContextStruct>::AndTrigger(
|
||||
std::unique_ptr<Trigger<TriggerContextStruct>> A,
|
||||
std::unique_ptr<Trigger<TriggerContextStruct>> B
|
||||
) : m_A(std::move(A)), m_B(std::move(B)) {}
|
||||
|
||||
template<typename TriggerContextStruct>
|
||||
bool AndTrigger<TriggerContextStruct>::check(const TriggerContextStruct &ctx) const {
|
||||
const bool valid = m_A->check(ctx) && m_B->check(ctx);
|
||||
if (valid) {
|
||||
m_hits++;
|
||||
} else {
|
||||
m_misses++;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
void AndTrigger<TriggerContextStruct>::update(const TriggerContextStruct &ctx) {
|
||||
m_A->update(ctx);
|
||||
m_B->update(ctx);
|
||||
m_updates++;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
void AndTrigger<TriggerContextStruct>::reset() {
|
||||
m_A->reset();
|
||||
m_B->reset();
|
||||
m_resets++;
|
||||
|
||||
m_hits = 0;
|
||||
m_misses = 0;
|
||||
m_updates = 0;
|
||||
}
|
||||
|
||||
template<typename TriggerContextStruct>
|
||||
std::string AndTrigger<TriggerContextStruct>::name() const {
|
||||
return "AND Trigger";
|
||||
}
|
||||
|
||||
template<typename TriggerContextStruct>
|
||||
TriggerResult AndTrigger<TriggerContextStruct>::why(const TriggerContextStruct &ctx) const {
|
||||
TriggerResult result;
|
||||
|
||||
result.name = name();
|
||||
|
||||
TriggerResult A_result = m_A->why(ctx);
|
||||
result.causes.push_back(A_result);
|
||||
|
||||
if (!A_result.value) {
|
||||
// Short Circuit
|
||||
result.value = false;
|
||||
result.description = "Failed because A (" + A_result.name + ") is false.";
|
||||
return result;
|
||||
}
|
||||
|
||||
TriggerResult B_result = m_B->why(ctx);
|
||||
result.causes.push_back(B_result);
|
||||
|
||||
if (!B_result.value) {
|
||||
result.value = false;
|
||||
result.description = "Failed because B (" + B_result.name + ") is false.";
|
||||
return result;
|
||||
}
|
||||
|
||||
result.value = true;
|
||||
result.description = "Succeeded because both A (" + A_result.name + ") and B (" + B_result.description + ") are true.";
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
std::string AndTrigger<TriggerContextStruct>::describe() const {
|
||||
return "(" + m_A->describe() + ") AND (" + m_B->describe() + ")";
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
size_t AndTrigger<TriggerContextStruct>::numTriggers() const {
|
||||
return m_hits;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
size_t AndTrigger<TriggerContextStruct>::numMisses() const {
|
||||
return m_misses;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
OrTrigger<TriggerContextStruct>::OrTrigger(
|
||||
std::unique_ptr<Trigger<TriggerContextStruct>> A,
|
||||
std::unique_ptr<Trigger<TriggerContextStruct>> B
|
||||
) : m_A(std::move(A)), m_B(std::move(B)) {}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
bool OrTrigger<TriggerContextStruct>::check(const TriggerContextStruct &ctx) const {
|
||||
const bool valid = m_A->check(ctx) || m_B->check(ctx);
|
||||
if (valid) {
|
||||
m_hits++;
|
||||
} else {
|
||||
m_misses++;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
void OrTrigger<TriggerContextStruct>::update(const TriggerContextStruct &ctx) {
|
||||
m_A->update(ctx);
|
||||
m_B->update(ctx);
|
||||
m_updates++;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
void OrTrigger<TriggerContextStruct>::reset() {
|
||||
m_A->reset();
|
||||
m_B->reset();
|
||||
m_resets++;
|
||||
|
||||
m_hits = 0;
|
||||
m_misses = 0;
|
||||
m_updates = 0;
|
||||
}
|
||||
|
||||
template<typename TriggerContextStruct>
|
||||
std::string OrTrigger<TriggerContextStruct>::name() const {
|
||||
return "OR Trigger";
|
||||
}
|
||||
|
||||
template<typename TriggerContextStruct>
|
||||
TriggerResult OrTrigger<TriggerContextStruct>::why(const TriggerContextStruct &ctx) const {
|
||||
TriggerResult result;
|
||||
result.name = name();
|
||||
|
||||
TriggerResult A_result = m_A->why(ctx);
|
||||
result.causes.push_back(A_result);
|
||||
|
||||
if (A_result.value) {
|
||||
// Short Circuit
|
||||
result.value = true;
|
||||
result.description = "Succeeded because A (" + A_result.name + ") is true.";
|
||||
return result;
|
||||
}
|
||||
|
||||
TriggerResult B_result = m_B->why(ctx);
|
||||
result.causes.push_back(B_result);
|
||||
|
||||
if (B_result.value) {
|
||||
result.value = true;
|
||||
result.description = "Succeeded because B (" + B_result.name + ") is true.";
|
||||
return result;
|
||||
}
|
||||
|
||||
result.value = false;
|
||||
result.description = "Failed because both A (" + A_result.name + ") and B (" + B_result.name + ") are false.";
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
std::string OrTrigger<TriggerContextStruct>::describe() const {
|
||||
return "(" + m_A->describe() + ") OR (" + m_B->describe() + ")";
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
size_t OrTrigger<TriggerContextStruct>::numTriggers() const {
|
||||
return m_hits;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
size_t OrTrigger<TriggerContextStruct>::numMisses() const {
|
||||
return m_misses;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
NotTrigger<TriggerContextStruct>::NotTrigger(
|
||||
std::unique_ptr<Trigger<TriggerContextStruct>> A
|
||||
) : m_A(std::move(A)) {}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
bool NotTrigger<TriggerContextStruct>::check(const TriggerContextStruct &ctx) const {
|
||||
const bool valid = !m_A->check(ctx);
|
||||
if (valid) {
|
||||
m_hits++;
|
||||
} else {
|
||||
m_misses++;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
void NotTrigger<TriggerContextStruct>::update(const TriggerContextStruct &ctx) {
|
||||
m_A->update(ctx);
|
||||
m_updates++;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
void NotTrigger<TriggerContextStruct>::reset() {
|
||||
m_A->reset();
|
||||
m_resets++;
|
||||
|
||||
m_hits = 0;
|
||||
m_misses = 0;
|
||||
m_updates = 0;
|
||||
}
|
||||
|
||||
template<typename TriggerContextStruct>
|
||||
std::string NotTrigger<TriggerContextStruct>::name() const {
|
||||
return "NOT Trigger";
|
||||
}
|
||||
|
||||
template<typename TriggerContextStruct>
|
||||
TriggerResult NotTrigger<TriggerContextStruct>::why(const TriggerContextStruct &ctx) const {
|
||||
TriggerResult result;
|
||||
result.name = name();
|
||||
|
||||
TriggerResult A_result = m_A->why(ctx);
|
||||
result.causes.push_back(A_result);
|
||||
if (A_result.value) {
|
||||
result.value = false;
|
||||
result.description = "Failed because A (" + A_result.name + ") is true.";
|
||||
return result;
|
||||
}
|
||||
result.value = true;
|
||||
result.description = "Succeeded because A (" + A_result.name + ") is false.";
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
std::string NotTrigger<TriggerContextStruct>::describe() const {
|
||||
return "NOT (" + m_A->describe() + ")";
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
size_t NotTrigger<TriggerContextStruct>::numTriggers() const {
|
||||
return m_hits;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
size_t NotTrigger<TriggerContextStruct>::numMisses() const {
|
||||
return m_misses;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
EveryNthTrigger<TriggerContextStruct>::EveryNthTrigger(std::unique_ptr<Trigger<TriggerContextStruct>> A, const size_t N) : m_A(std::move(A)), m_N(N) {
|
||||
if (N == 0) {
|
||||
throw std::invalid_argument("N must be greater than 0.");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
bool EveryNthTrigger<TriggerContextStruct>::check(const TriggerContextStruct &ctx) const
|
||||
{
|
||||
if (m_A->check(ctx) && (m_counter % m_N == 0)) {
|
||||
m_hits++;
|
||||
return true;
|
||||
}
|
||||
m_misses++;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
void EveryNthTrigger<TriggerContextStruct>::update(const TriggerContextStruct &ctx) {
|
||||
if (m_A->check(ctx)) {
|
||||
m_counter++;
|
||||
}
|
||||
m_A->update(ctx);
|
||||
m_updates++;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
void EveryNthTrigger<TriggerContextStruct>::reset() {
|
||||
m_A->reset();
|
||||
m_resets++;
|
||||
|
||||
m_counter = 0;
|
||||
m_hits = 0;
|
||||
m_misses = 0;
|
||||
m_updates = 0;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
std::string EveryNthTrigger<TriggerContextStruct>::name() const {
|
||||
return "Every Nth Trigger";
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
TriggerResult EveryNthTrigger<TriggerContextStruct>::why(const TriggerContextStruct &ctx) const {
|
||||
TriggerResult result;
|
||||
result.name = name();
|
||||
TriggerResult A_result = m_A->why(ctx);
|
||||
result.causes.push_back(A_result);
|
||||
if (!A_result.value) {
|
||||
result.value = false;
|
||||
result.description = "Failed because A (" + A_result.name + ") is false.";
|
||||
return result;
|
||||
}
|
||||
if (m_counter % m_N == 0) {
|
||||
result.value = true;
|
||||
result.description = "Succeeded because A (" + A_result.name + ") is true and the counter (" + std::to_string(m_counter) + ") is a multiple of N (" + std::to_string(m_N) + ").";
|
||||
return result;
|
||||
}
|
||||
result.value = false;
|
||||
result.description = "Failed because the counter (" + std::to_string(m_counter) + ") is not a multiple of N (" + std::to_string(m_N) + ").";
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
std::string EveryNthTrigger<TriggerContextStruct>::describe() const {
|
||||
return "Every " + std::to_string(m_N) + "th (" + m_A->describe() + ")";
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
size_t EveryNthTrigger<TriggerContextStruct>::numTriggers() const {
|
||||
return m_hits;
|
||||
}
|
||||
|
||||
template <typename TriggerContextStruct>
|
||||
size_t EveryNthTrigger<TriggerContextStruct>::numMisses() const {
|
||||
return m_misses;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
13
src/include/gridfire/trigger/trigger_result.h
Normal file
13
src/include/gridfire/trigger/trigger_result.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace gridfire::trigger {
|
||||
struct TriggerResult {
|
||||
std::string name;
|
||||
std::string description;
|
||||
bool value;
|
||||
std::vector<TriggerResult> causes;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user