Skip to content
6 changes: 5 additions & 1 deletion src/wmtk/invariants/Invariant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <wmtk/Mesh.hpp>
#include <wmtk/simplex/Simplex.hpp>
#include <wmtk/simplex/top_dimension_cofaces.hpp>
#include <wmtk/utils/Logger.hpp>
#include <wmtk/utils/primitive_range.hpp>

namespace wmtk::invariants {
Expand Down Expand Up @@ -57,7 +58,10 @@ bool Invariant::directly_modified_after(

return true;
}

bool Invariant::is_collection() const
{
return false;
}
bool Invariant::use_old_state_in_after() const
{
return m_use_old_state_in_after;
Expand Down
5 changes: 5 additions & 0 deletions src/wmtk/invariants/Invariant.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#pragma once
#include <array>
#include <vector>
#include <wmtk/PrimitiveType.hpp>
namespace wmtk {
Expand Down Expand Up @@ -30,6 +31,7 @@ class Invariant

const Mesh& mesh() const;

// A compact pipeline for evaluating after without computing any cofaces
// TODO change name
virtual bool directly_modified_after(
const std::vector<simplex::Simplex>& simplices_before,
Expand All @@ -41,12 +43,15 @@ class Invariant
bool use_old_state_in_after() const;
bool use_new_state_in_after() const;

virtual bool is_collection() const;

private:
const Mesh& m_mesh;
const bool m_use_before = true;
const bool m_use_old_state_in_after = true;
const bool m_use_new_state_in_after = true;

protected:
const std::vector<Tuple> get_top_dimension_cofaces(
const std::vector<simplex::Simplex>& simplices) const;
};
Expand Down
63 changes: 60 additions & 3 deletions src/wmtk/invariants/InvariantCollection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
#include <type_traits>
#include <wmtk/Mesh.hpp>
#include <wmtk/simplex/Simplex.hpp>
#include <wmtk/utils/Logger.hpp>

namespace wmtk::invariants {

InvariantCollection::InvariantCollection(const Mesh& m)
: Invariant(m, true, true, true)
{}
{
m_use_same_mesh_caching = true;
}
InvariantCollection::~InvariantCollection() = default;
InvariantCollection::InvariantCollection(const InvariantCollection&) = default;
InvariantCollection::InvariantCollection(InvariantCollection&&) = default;
Expand All @@ -26,7 +29,10 @@ InvariantCollection& InvariantCollection::operator=(InvariantCollection&& o)

void InvariantCollection::add(std::shared_ptr<Invariant> invariant)
{
m_invariants.emplace_back(std::move(invariant));
const auto& invar = m_invariants.emplace_back(std::move(invariant));
if (m_use_same_mesh_caching && &mesh() == &invar->mesh()) {
m_same_mesh_invariants.emplace_back(invar);
}
}
bool InvariantCollection::before(const simplex::Simplex& t) const
{
Expand Down Expand Up @@ -113,12 +119,62 @@ bool InvariantCollection::directly_modified_after(
mapped_simplices_after)) {
return false;
}
} else {
} else if (!m_use_same_mesh_caching) {
if (!invariant->directly_modified_after(simplices_before, simplices_after)) {
return false;
}
}
}
if (m_use_same_mesh_caching) {
std::vector<Tuple> tuples_before, tuples_after;
return directly_modified_after_cached(
simplices_before,
simplices_after,
tuples_before,
tuples_after);
}
return true;
}
bool InvariantCollection::is_collection() const
{
return true;
}

bool InvariantCollection::directly_modified_after_cached(
const std::vector<simplex::Simplex>& simplices_before,
const std::vector<simplex::Simplex>& simplices_after,
std::vector<Tuple>& cofaces_before,
std::vector<Tuple>& cofaces_after) const
{
for (const auto& invariant_ptr : m_same_mesh_invariants) {
const auto& invariant = *invariant_ptr;
assert(&mesh() == &invariant.mesh());
if (invariant.is_collection()) {
if (!static_cast<const InvariantCollection&>(invariant).directly_modified_after_cached(
simplices_before,
simplices_after,
cofaces_before,
cofaces_after)) {
return false;
}
} else if (invariant.use_after()) {
if (invariant.use_new_state_in_after()) {
if (cofaces_after.empty()) {
cofaces_after = get_top_dimension_cofaces(simplices_after);
}
}
if (invariant.use_old_state_in_after()) {
if (cofaces_before.empty()) {
cofaces_before = mesh().parent_scope(
[&]() { return get_top_dimension_cofaces(simplices_before); });
}
}

if (!after(cofaces_before, cofaces_after)) {
return false;
}
}
}
return true;
}

Expand Down Expand Up @@ -164,4 +220,5 @@ InvariantCollection::get_map_mesh_to_invariants()
//
}


} // namespace wmtk::invariants
13 changes: 12 additions & 1 deletion src/wmtk/invariants/InvariantCollection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,17 @@ class InvariantCollection : public Invariant

bool directly_modified_after(
const std::vector<simplex::Simplex>& simplices_before,
const std::vector<simplex::Simplex>& simplices_after) const override;
const std::vector<simplex::Simplex>& simplices_after) const final override;

// optimization for evaluating connected subgraphs of invariants that share the same mesh
// In this case we can cache the cofaces computed once rather than re-evaluate them
bool directly_modified_after_cached(
const std::vector<simplex::Simplex>& simplices_before,
const std::vector<simplex::Simplex>& simplices_after,
std::vector<Tuple>& cofaces_before,
std::vector<Tuple>& cofaces_after) const;

bool is_collection() const final override;
// pass by value so this can be internally moved
void add(std::shared_ptr<Invariant> invariant);

Expand All @@ -44,6 +53,8 @@ class InvariantCollection : public Invariant

private:
std::vector<std::shared_ptr<Invariant>> m_invariants;
std::vector<std::shared_ptr<Invariant>> m_same_mesh_invariants;
bool m_use_same_mesh_caching = false;
};

} // namespace invariants
Expand Down
33 changes: 22 additions & 11 deletions src/wmtk/multimesh/MultiMeshManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -504,10 +504,14 @@ std::vector<Tuple> MultiMeshManager::map_tuples(

int64_t depth = my_id.size();

auto [root_ref, tuple] = map_up_to_tuples(my_mesh, my_simplex, depth);
const simplex::Simplex simplex(root_ref, my_simplex.primitive_type(), tuple);
if (is_root()) {
return my_mesh.m_multi_mesh_manager.map_down_relative_tuples(my_mesh, my_simplex, other_id);
} else {
auto [root_ref, tuple] = map_up_to_tuples(my_mesh, my_simplex, depth);
const simplex::Simplex simplex(root_ref, my_simplex.primitive_type(), tuple);

return root_ref.m_multi_mesh_manager.map_down_relative_tuples(root_ref, simplex, other_id);
return root_ref.m_multi_mesh_manager.map_down_relative_tuples(root_ref, simplex, other_id);
}
}

std::vector<Tuple> MultiMeshManager::lub_map_tuples(
Expand All @@ -524,16 +528,23 @@ std::vector<Tuple> MultiMeshManager::lub_map_tuples(

int64_t depth = my_id.size() - lub_id.size();

auto [local_root_ref, tuple] = map_up_to_tuples(my_mesh, my_simplex, depth);
assert(other_mesh.m_multi_mesh_manager.is_child(other_mesh, local_root_ref));
auto other_relative_id = relative_id(lub_id, other_id);
if (depth == 0) {
return my_mesh.m_multi_mesh_manager.map_down_relative_tuples(
my_mesh,
my_simplex,
other_relative_id);
} else {
auto [local_root_ref, tuple] = map_up_to_tuples(my_mesh, my_simplex, depth);
assert(other_mesh.m_multi_mesh_manager.is_child(other_mesh, local_root_ref));

const simplex::Simplex simplex(local_root_ref, my_simplex.primitive_type(), tuple);
const simplex::Simplex simplex(local_root_ref, my_simplex.primitive_type(), tuple);

auto other_relative_id = relative_id(lub_id, other_id);
return local_root_ref.m_multi_mesh_manager.map_down_relative_tuples(
local_root_ref,
simplex,
other_relative_id);
return local_root_ref.m_multi_mesh_manager.map_down_relative_tuples(
local_root_ref,
simplex,
other_relative_id);
}
}

simplex::Simplex MultiMeshManager::map_to_root(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,25 +48,25 @@ std::vector<Tuple> AttributeTransferStrategyBase::get_parent_simplices(

if (my_primitive_type != parent_primitive_type) {
// lambda for running either of the cases
std::vector<Tuple> r;
if (parent_tuples.size() == 1) {
r = simplex::neighbors_single_dimension_tuples(
parent_tuples = simplex::neighbors_single_dimension_tuples(
m,
simplex::Simplex(m, my_primitive_type, parent_tuples[0]),
simplex::Simplex(my_primitive_type, parent_tuples[0]),
parent_primitive_type);
} else {
std::vector<Tuple> r;
for (const auto& parent_tup : parent_tuples) {
std::vector<Tuple> c = simplex::neighbors_single_dimension_tuples(
m,
simplex::Simplex(m, my_primitive_type, parent_tup),
simplex::Simplex(my_primitive_type, parent_tup),
parent_primitive_type);
std::copy(c.begin(), c.end(), std::back_inserter(r));
}
if (parent_tuples.size() > 1) {
simplex::utils::unique_homogeneous_simplices_inline(m, parent_primitive_type, r);
}
parent_tuples = std::move(r);
}
parent_tuples = std::move(r);
}
return parent_tuples;
}
Expand Down
1 change: 0 additions & 1 deletion src/wmtk/simplex/Simplex.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ class Simplex
Tuple m_tuple;

public:
// the mesh class can use this index value to cache/accelerate operations
Simplex(const PrimitiveType& ptype, const Tuple& t)
: m_primitive_type{ptype}
, m_tuple{t}
Expand Down