3#include <wmtk/ExecutionScheduler.hpp>
4#include <wmtk/threading/collector.hpp>
50size_t run_localized_to_convergence(
52 ExecutePass<Mesh>& executor,
53 OpList<typename Mesh::Tuple> ops,
54 size_t max_passes = 0)
56 using Tuple =
typename Mesh::Tuple;
61 std::vector<uint64_t> vertex_epoch(m.vert_capacity(), 0);
67 std::vector<Op> op_names;
68 op_names.reserve(executor.edit_operation_maps.size());
69 for (
const auto& kv : executor.edit_operation_maps) {
70 op_names.push_back(kv.first);
74 std::mutex failures_mutex;
75 std::deque<std::pair<uint32_t, Tuple>> failures;
77 auto edge_epoch = [&vertex_epoch](
const Mesh& m_,
const Tuple& t) -> uint64_t {
78 const size_t a = t.vid(m_);
79 const size_t b = t.switch_vertex(m_).vid(m_);
80 const uint64_t ea = a < vertex_epoch.size() ? vertex_epoch[a] : 0;
81 const uint64_t eb = b < vertex_epoch.size() ? vertex_epoch[b] : 0;
82 return std::max(ea, eb);
88 auto driver_renew = executor.renew_neighbor_tuples;
89 executor.renew_neighbor_tuples =
90 [&, driver_renew](
const Mesh& m_, Op op,
const std::vector<Tuple>& newts) {
91 auto tups = driver_renew(m_, op, newts);
92 for (
const auto& [_, t] : tups) {
93 const size_t a = t.vid(m_);
94 const size_t b = t.switch_vertex(m_).vid(m_);
95 if (a < vertex_epoch.size()) {
98 vertex_epoch[a] = round;
100 if (b < vertex_epoch.size()) {
101 vertex_epoch[b] = round;
106 executor.on_fail = [&failures, &failures_mutex, &op_names](
const Mesh&, Op op,
const Tuple& t) {
107 const auto it = std::lower_bound(op_names.begin(), op_names.end(), op);
108 assert(it != op_names.end() && *it == op);
109 std::lock_guard<std::mutex> lock(failures_mutex);
110 failures.emplace_back(
static_cast<uint32_t
>(it - op_names.begin()), t);
113 size_t total_success = 0;
118 executor(m, std::move(ops));
119 total_success +=
static_cast<size_t>(executor.get_cnt_success());
121 for (
const auto& pr : failures) {
122 const Tuple& t = pr.second;
123 if (!t.is_valid(m)) {
127 if (edge_epoch(m, t) == round) {
128 ops.emplace_back(op_names[pr.first], t);
131 }
while (executor.get_cnt_success() > 0 && !ops.empty() &&
132 (max_passes == 0 || round < max_passes));
133 return total_success;