feat(EnginePartitioningTrigger): update trigger
Engine Partitioning trigger now properly throws on both increased convergence failures and a timestep collapse (timestep collapsing more than a factor of 1/100th the average value for the past 10 steps)
This commit is contained in:
@@ -331,8 +331,7 @@ namespace gridfire::trigger::solver::CVODE {
|
|||||||
*
|
*
|
||||||
* @param simulationTimeInterval Interval used by SimulationTimeTrigger (> 0).
|
* @param simulationTimeInterval Interval used by SimulationTimeTrigger (> 0).
|
||||||
* @param offDiagonalThreshold Off-diagonal Jacobian magnitude threshold (>= 0).
|
* @param offDiagonalThreshold Off-diagonal Jacobian magnitude threshold (>= 0).
|
||||||
* @param timestepGrowthThreshold Threshold for timestep deviation (>= 0, and <= 1 when relative).
|
* @param relativeTimestepCollapseThreshold Threshold for timestep deviation (>= 0, and <= 1 when relative).
|
||||||
* @param timestepGrowthRelative Whether deviation is measured relatively.
|
|
||||||
* @param timestepGrowthWindowSize Window size for timestep averaging (>= 1 recommended).
|
* @param timestepGrowthWindowSize Window size for timestep averaging (>= 1 recommended).
|
||||||
* @return A unique_ptr to a composed Trigger<TimestepContext> implementing the policy above.
|
* @return A unique_ptr to a composed Trigger<TimestepContext> implementing the policy above.
|
||||||
*
|
*
|
||||||
@@ -341,8 +340,7 @@ namespace gridfire::trigger::solver::CVODE {
|
|||||||
std::unique_ptr<Trigger<gridfire::solver::CVODESolverStrategy::TimestepContext>> makeEnginePartitioningTrigger(
|
std::unique_ptr<Trigger<gridfire::solver::CVODESolverStrategy::TimestepContext>> makeEnginePartitioningTrigger(
|
||||||
const double simulationTimeInterval,
|
const double simulationTimeInterval,
|
||||||
const double offDiagonalThreshold,
|
const double offDiagonalThreshold,
|
||||||
const double timestepGrowthThreshold,
|
const double relativeTimestepCollapseThreshold,
|
||||||
const bool timestepGrowthRelative,
|
|
||||||
const size_t timestepGrowthWindowSize
|
const size_t timestepGrowthWindowSize
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ namespace gridfire::solver {
|
|||||||
) {
|
) {
|
||||||
LOG_TRACE_L1(m_logger, "Starting solver evaluation with T9: {} and rho: {}", netIn.temperature/1e9, netIn.density);
|
LOG_TRACE_L1(m_logger, "Starting solver evaluation with T9: {} and rho: {}", netIn.temperature/1e9, netIn.density);
|
||||||
LOG_TRACE_L1(m_logger, "Building engine update trigger....");
|
LOG_TRACE_L1(m_logger, "Building engine update trigger....");
|
||||||
auto trigger = trigger::solver::CVODE::makeEnginePartitioningTrigger(1e12, 1e10, 1, true, 10);
|
auto trigger = trigger::solver::CVODE::makeEnginePartitioningTrigger(1e12, 1e10, 0.01, 10);
|
||||||
LOG_TRACE_L1(m_logger, "Engine update trigger built!");
|
LOG_TRACE_L1(m_logger, "Engine update trigger built!");
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ namespace gridfire::trigger::solver::CVODE {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TimestepCollapseTrigger::check(const gridfire::solver::CVODESolverStrategy::TimestepContext &ctx) const {
|
bool TimestepCollapseTrigger::check(const gridfire::solver::CVODESolverStrategy::TimestepContext &ctx) const {
|
||||||
if (m_timestep_window.empty()) {
|
if (m_timestep_window.size() < m_windowSize) {
|
||||||
m_misses++;
|
m_misses++;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -193,11 +193,16 @@ namespace gridfire::trigger::solver::CVODE {
|
|||||||
averageTimestep += dt;
|
averageTimestep += dt;
|
||||||
}
|
}
|
||||||
averageTimestep /= static_cast<double>(m_timestep_window.size());
|
averageTimestep /= static_cast<double>(m_timestep_window.size());
|
||||||
if (m_relative && (std::abs(ctx.dt - averageTimestep) / averageTimestep) >= m_threshold) {
|
if (ctx.dt > averageTimestep) {
|
||||||
|
m_misses++;
|
||||||
|
return false; // Only trigger on timestep collapse (i.e., decrease in dt)
|
||||||
|
}
|
||||||
|
const double diff = std::abs(ctx.dt - averageTimestep);
|
||||||
|
if (m_relative && 1-(diff / averageTimestep) <= m_threshold) {
|
||||||
m_hits++;
|
m_hits++;
|
||||||
LOG_TRACE_L2(m_logger, "TimestepCollapseTrigger triggered at t = {} due to relative growth: dt = {}, average dt = {}, threshold = {}", ctx.t, ctx.dt, averageTimestep, m_threshold);
|
LOG_TRACE_L2(m_logger, "TimestepCollapseTrigger triggered at t = {} due to relative growth: dt = {}, average dt = {}, threshold = {}", ctx.t, ctx.dt, averageTimestep, m_threshold);
|
||||||
return true;
|
return true;
|
||||||
} else if (!m_relative && std::abs(ctx.dt - averageTimestep) >= m_threshold) {
|
} else if (!m_relative && diff >= m_threshold) {
|
||||||
m_hits++;
|
m_hits++;
|
||||||
LOG_TRACE_L2(m_logger, "TimestepCollapseTrigger triggered at t = {} due to absolute growth: dt = {}, average dt = {}, threshold = {}", ctx.t, ctx.dt, averageTimestep, m_threshold);
|
LOG_TRACE_L2(m_logger, "TimestepCollapseTrigger triggered at t = {} due to absolute growth: dt = {}, average dt = {}, threshold = {}", ctx.t, ctx.dt, averageTimestep, m_threshold);
|
||||||
return true;
|
return true;
|
||||||
@@ -207,13 +212,13 @@ namespace gridfire::trigger::solver::CVODE {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TimestepCollapseTrigger::update(const gridfire::solver::CVODESolverStrategy::TimestepContext &ctx) {
|
void TimestepCollapseTrigger::update(const gridfire::solver::CVODESolverStrategy::TimestepContext &ctx) {
|
||||||
push_to_fixed_deque(m_timestep_window, ctx.dt, m_windowSize);
|
|
||||||
m_updates++;
|
m_updates++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimestepCollapseTrigger::step(
|
void TimestepCollapseTrigger::step(
|
||||||
const gridfire::solver::CVODESolverStrategy::TimestepContext &ctx
|
const gridfire::solver::CVODESolverStrategy::TimestepContext &ctx
|
||||||
) {
|
) {
|
||||||
|
push_to_fixed_deque(m_timestep_window, ctx.dt, m_windowSize);
|
||||||
// --- TimestepCollapseTrigger::step does nothing and is intentionally left blank --- //
|
// --- TimestepCollapseTrigger::step does nothing and is intentionally left blank --- //
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,8 +378,7 @@ namespace gridfire::trigger::solver::CVODE {
|
|||||||
std::unique_ptr<Trigger<gridfire::solver::CVODESolverStrategy::TimestepContext>> makeEnginePartitioningTrigger(
|
std::unique_ptr<Trigger<gridfire::solver::CVODESolverStrategy::TimestepContext>> makeEnginePartitioningTrigger(
|
||||||
const double simulationTimeInterval,
|
const double simulationTimeInterval,
|
||||||
const double offDiagonalThreshold,
|
const double offDiagonalThreshold,
|
||||||
const double timestepGrowthThreshold,
|
const double relativeTimestepCollapseThreshold,
|
||||||
const bool timestepGrowthRelative,
|
|
||||||
const size_t timestepGrowthWindowSize
|
const size_t timestepGrowthWindowSize
|
||||||
) {
|
) {
|
||||||
using ctx_t = gridfire::solver::CVODESolverStrategy::TimestepContext;
|
using ctx_t = gridfire::solver::CVODESolverStrategy::TimestepContext;
|
||||||
@@ -389,14 +393,12 @@ namespace gridfire::trigger::solver::CVODE {
|
|||||||
// TODO: This logic likely needs to be revisited; however, for now it is easy enough to change and test and it works reasonably well
|
// TODO: This logic likely needs to be revisited; however, for now it is easy enough to change and test and it works reasonably well
|
||||||
auto simulationTimeTrigger = std::make_unique<EveryNthTrigger<ctx_t>>(std::make_unique<SimulationTimeTrigger>(simulationTimeInterval), 1000);
|
auto simulationTimeTrigger = std::make_unique<EveryNthTrigger<ctx_t>>(std::make_unique<SimulationTimeTrigger>(simulationTimeInterval), 1000);
|
||||||
auto offDiagTrigger = std::make_unique<OffDiagonalTrigger>(offDiagonalThreshold);
|
auto offDiagTrigger = std::make_unique<OffDiagonalTrigger>(offDiagonalThreshold);
|
||||||
auto timestepGrowthTrigger = std::make_unique<EveryNthTrigger<ctx_t>>(std::make_unique<TimestepCollapseTrigger>(timestepGrowthThreshold, timestepGrowthRelative, timestepGrowthWindowSize), 10);
|
auto timestepGrowthTrigger = std::make_unique<EveryNthTrigger<ctx_t>>(std::make_unique<TimestepCollapseTrigger>(relativeTimestepCollapseThreshold, true, timestepGrowthWindowSize), 10);
|
||||||
auto convergenceFailureTrigger = std::make_unique<ConvergenceFailureTrigger>(5, 1.0f, 10);
|
auto convergenceFailureTrigger = std::make_unique<ConvergenceFailureTrigger>(5, 1.0f, 10);
|
||||||
|
|
||||||
// Combine the triggers using logical OR
|
|
||||||
auto orTriggerA = std::make_unique<OrTrigger<ctx_t>>(std::move(simulationTimeTrigger), std::move(offDiagTrigger));
|
|
||||||
auto orTriggerB = std::make_unique<OrTrigger<ctx_t>>(std::move(orTriggerA), std::move(timestepGrowthTrigger));
|
|
||||||
// auto orTriggerC = std::make_unique<OrTrigger<ctx_t>>(std::move(orTriggerB), std::move(convergenceFailureTrigger));
|
|
||||||
|
|
||||||
return convergenceFailureTrigger;
|
auto convergenceOrTimestepTrigger = std::make_unique<OrTrigger<ctx_t>>(std::move(timestepGrowthTrigger), std::move(convergenceFailureTrigger));
|
||||||
|
|
||||||
|
return convergenceOrTimestepTrigger;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user