3#include <wmtk/ExecutionScheduler.hpp>
4#include <wmtk/threading/collector.hpp>
46size_t run_localized_to_convergence(
48 ExecutePass<Mesh>& executor,
49 std::vector<std::pair<Op, typename Mesh::Tuple>> ops,
50 size_t max_passes = 0)
52 using Tuple =
typename Mesh::Tuple;
57 std::vector<uint64_t> vertex_epoch(m.vert_capacity(), 0);
59 threading::collector<std::pair<Op, Tuple>> failures;
61 auto edge_epoch = [&vertex_epoch](
const Mesh& m_,
const Tuple& t) -> uint64_t {
62 const size_t a = t.vid(m_);
63 const size_t b = t.switch_vertex(m_).vid(m_);
64 const uint64_t ea = a < vertex_epoch.size() ? vertex_epoch[a] : 0;
65 const uint64_t eb = b < vertex_epoch.size() ? vertex_epoch[b] : 0;
66 return std::max(ea, eb);
72 auto driver_renew = executor.renew_neighbor_tuples;
73 executor.renew_neighbor_tuples =
74 [&, driver_renew](
const Mesh& m_, Op op,
const std::vector<Tuple>& newts) {
75 auto tups = driver_renew(m_, op, newts);
76 for (
const auto& [_, t] : tups) {
77 const size_t a = t.vid(m_);
78 const size_t b = t.switch_vertex(m_).vid(m_);
79 if (a < vertex_epoch.size()) {
82 vertex_epoch[a] = round;
84 if (b < vertex_epoch.size()) {
85 vertex_epoch[b] = round;
90 executor.on_fail = [&failures](
const Mesh&, Op op,
const Tuple& t) {
91 failures.emplace_back(op, t);
94 size_t total_success = 0;
99 total_success +=
static_cast<size_t>(executor.get_cnt_success());
101 for (
const auto& pr : failures) {
102 const Tuple& t = pr.second;
103 if (!t.is_valid(m)) {
107 if (edge_epoch(m, t) == round) {
108 ops.emplace_back(pr);
111 }
while (executor.get_cnt_success() > 0 && !ops.empty() &&
112 (max_passes == 0 || round < max_passes));
113 return total_success;