From ba90699d0c33057ac7e6e1766857213bc718c19a Mon Sep 17 00:00:00 2001 From: zhouyuan chen <867442167@qq.com> Date: Thu, 21 Sep 2023 22:45:52 -0400 Subject: [PATCH 01/49] add dummy files --- src/wmtk/CMakeLists.txt | 2 ++ src/wmtk/EdgeMesh.cpp | 78 +++++++++++++++++++++++++++++++++++++++++ src/wmtk/EdgeMesh.hpp | 50 ++++++++++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 src/wmtk/EdgeMesh.cpp create mode 100644 src/wmtk/EdgeMesh.hpp diff --git a/src/wmtk/CMakeLists.txt b/src/wmtk/CMakeLists.txt index 86b477eb92..391bcb4538 100644 --- a/src/wmtk/CMakeLists.txt +++ b/src/wmtk/CMakeLists.txt @@ -5,6 +5,8 @@ set(SRC_FILES Mesh.hpp PointMesh.cpp PointMesh.hpp + EdgeMesh.hpp + EdgeMesh.cpp TriMesh.cpp TriMesh.hpp TetMesh.cpp diff --git a/src/wmtk/EdgeMesh.cpp b/src/wmtk/EdgeMesh.cpp new file mode 100644 index 0000000000..b407e98aa7 --- /dev/null +++ b/src/wmtk/EdgeMesh.cpp @@ -0,0 +1,78 @@ +#include "EdgeMesh" +namespace wmtk { +Tuple EdgeMesh::vertex_tuple_from_id(long id) const +{ + return Tuple(-1, -1, -1, id, get_cell_hash_slow(id)); +} + +EdgeMesh::EdgeMesh() + : Mesh(0) +{} + + +EdgeMesh::EdgeMesh(long size) + : PointMesh() +{ + initialize(size); +} + +Tuple EdgeMesh::switch_tuple(const Tuple& tuple, PrimitiveType type) const +{ + throw std::runtime_error("Tuple switch: Invalid primitive type"); + return tuple; +} +bool EdgeMesh::is_ccw(const Tuple&) const +{ + // trivial orientation so nothing can happen + return true; +} +bool EdgeMesh::is_boundary(const Tuple&) const +{ + // every point is on the interior as it has no boundary simplices + return false; +} + +bool EdgeMesh::is_boundary_vertex(const Tuple&) const +{ + // every point is on the interior as it has no boundary simplices + return false; +} + +void EdgeMesh::initialize(long count) +{ + set_capacities({count}); + reserve_attributes_to_fit(); + Accessor v_flag_accessor = get_flag_accessor(PrimitiveType::Vertex); + for (long i = 0; i < capacity(PrimitiveType::Vertex); ++i) { + v_flag_accessor.index_access().scalar_attribute(i) |= 0x1; + } +} + + +bool EdgeMesh::is_valid(const Tuple& tuple, ConstAccessor& hash_accessor) const +{ + if (tuple.is_null()) return false; + return true; + return Mesh::is_hash_valid(tuple, hash_accessor); + +} + +long EdgeMesh::id(const Tuple& tuple, PrimitiveType type) const +{ + switch (type) { + case PrimitiveType::Vertex: return tuple.m_global_cid; + case PrimitiveType::Edge: + case PrimitiveType::Face: + case PrimitiveType::Tetrahedron: + default: throw std::runtime_error("Tuple switch: Invalid primitive type"); break; + } +} + +Tuple EdgeMesh::tuple_from_id(const PrimitiveType type, const long gid) const +{ + if (type != PrimitiveType::Vertex) { + throw std::runtime_error("Tuple switch: Invalid primitive type"); + } + return vertex_tuple_from_id(gid); +} +} // namespace wmtk diff --git a/src/wmtk/EdgeMesh.hpp b/src/wmtk/EdgeMesh.hpp new file mode 100644 index 0000000000..f0b471087d --- /dev/null +++ b/src/wmtk/EdgeMesh.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "Mesh.hpp" +#include "Tuple.hpp" + +#include + +namespace wmtk { +// Simple mesh without topology. Mainly useful for testing attributes without having to construct +// topologies +class EdgeMesh : public Mesh +{ +private: + Tuple vertex_tuple_from_id(long id) const; + +public: + EdgeMesh(); + EdgeMesh(long size); + + PrimitiveType top_simplex_type() const override { return PrimitiveType::Vertex; } + Tuple switch_tuple(const Tuple& tuple, PrimitiveType type) const override; + bool is_ccw(const Tuple& tuple) const override; + bool is_boundary(const Tuple& tuple) const override; + bool is_boundary_vertex(const Tuple& tuple) const override; + // TODO: should just write is_boundary(PrimitiveType) + bool is_boundary_edge(const Tuple& tuple) const override { return true; } + + void initialize(long count); + + + bool is_valid(const Tuple& tuple, ConstAccessor& hash_accessor) const override; + + Tuple split_edge(const Tuple&, Accessor&) override { return {}; } + Tuple collapse_edge(const Tuple&, Accessor&) override { return {}; } + bool is_connectivity_valid() const override { return true; } + +protected: + long id(const Tuple& tuple, PrimitiveType type) const override; + + /** + * @brief internal function that returns the tuple of requested type, and has the global index + * cid + * + * @param gid + * @return Tuple + */ + Tuple tuple_from_id(const PrimitiveType type, const long gid) const override; +}; + +} // namespace wmtk From 5095f9824f6e611e13177d742b37e1215ffccd6c Mon Sep 17 00:00:00 2001 From: zhouyuan chen <867442167@qq.com> Date: Fri, 22 Sep 2023 00:03:11 -0400 Subject: [PATCH 02/49] fixed problem --- src/wmtk/EdgeMesh.cpp | 5 ++--- src/wmtk/attribute/MutableAccessor.hpp | 4 +++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/wmtk/EdgeMesh.cpp b/src/wmtk/EdgeMesh.cpp index b407e98aa7..7d9dde2d5d 100644 --- a/src/wmtk/EdgeMesh.cpp +++ b/src/wmtk/EdgeMesh.cpp @@ -1,4 +1,4 @@ -#include "EdgeMesh" +#include "EdgeMesh.hpp" namespace wmtk { Tuple EdgeMesh::vertex_tuple_from_id(long id) const { @@ -11,7 +11,7 @@ EdgeMesh::EdgeMesh() EdgeMesh::EdgeMesh(long size) - : PointMesh() + : EdgeMesh() { initialize(size); } @@ -54,7 +54,6 @@ bool EdgeMesh::is_valid(const Tuple& tuple, ConstAccessor& hash_accessor) if (tuple.is_null()) return false; return true; return Mesh::is_hash_valid(tuple, hash_accessor); - } long EdgeMesh::id(const Tuple& tuple, PrimitiveType type) const diff --git a/src/wmtk/attribute/MutableAccessor.hpp b/src/wmtk/attribute/MutableAccessor.hpp index 57b54373e9..4524854774 100644 --- a/src/wmtk/attribute/MutableAccessor.hpp +++ b/src/wmtk/attribute/MutableAccessor.hpp @@ -15,6 +15,7 @@ class MutableAccessor : public ConstAccessor friend class wmtk::Mesh; friend class wmtk::TetMesh; friend class wmtk::TriMesh; + friend class wmtk::EdgeMesh; friend class wmtk::PointMesh; friend class wmtk::TriMeshOperationExecutor; using CachingBaseType = CachingAccessor; @@ -30,8 +31,9 @@ class MutableAccessor : public ConstAccessor using ConstAccessorType::vector_attribute; - using CachingBaseType::stack_depth; using CachingBaseType::has_stack; + using CachingBaseType::stack_depth; + protected: using ConstAccessorType::base_type; using ConstAccessorType::caching_base_type; From f792fb491fb58dc3a40aa872cbaf88bc002300ba Mon Sep 17 00:00:00 2001 From: zhouyuan chen <867442167@qq.com> Date: Fri, 22 Sep 2023 09:25:58 -0400 Subject: [PATCH 03/49] added throws for safety --- src/wmtk/EdgeMesh.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/wmtk/EdgeMesh.cpp b/src/wmtk/EdgeMesh.cpp index 7d9dde2d5d..b1275cae5a 100644 --- a/src/wmtk/EdgeMesh.cpp +++ b/src/wmtk/EdgeMesh.cpp @@ -2,6 +2,7 @@ namespace wmtk { Tuple EdgeMesh::vertex_tuple_from_id(long id) const { + throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); return Tuple(-1, -1, -1, id, get_cell_hash_slow(id)); } @@ -18,28 +19,33 @@ EdgeMesh::EdgeMesh(long size) Tuple EdgeMesh::switch_tuple(const Tuple& tuple, PrimitiveType type) const { + throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); throw std::runtime_error("Tuple switch: Invalid primitive type"); return tuple; } bool EdgeMesh::is_ccw(const Tuple&) const { + throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); // trivial orientation so nothing can happen return true; } bool EdgeMesh::is_boundary(const Tuple&) const { + throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); // every point is on the interior as it has no boundary simplices return false; } bool EdgeMesh::is_boundary_vertex(const Tuple&) const { + throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); // every point is on the interior as it has no boundary simplices return false; } void EdgeMesh::initialize(long count) { + throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); set_capacities({count}); reserve_attributes_to_fit(); Accessor v_flag_accessor = get_flag_accessor(PrimitiveType::Vertex); @@ -51,6 +57,7 @@ void EdgeMesh::initialize(long count) bool EdgeMesh::is_valid(const Tuple& tuple, ConstAccessor& hash_accessor) const { + throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); if (tuple.is_null()) return false; return true; return Mesh::is_hash_valid(tuple, hash_accessor); @@ -58,6 +65,7 @@ bool EdgeMesh::is_valid(const Tuple& tuple, ConstAccessor& hash_accessor) long EdgeMesh::id(const Tuple& tuple, PrimitiveType type) const { + throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); switch (type) { case PrimitiveType::Vertex: return tuple.m_global_cid; case PrimitiveType::Edge: @@ -69,6 +77,7 @@ long EdgeMesh::id(const Tuple& tuple, PrimitiveType type) const Tuple EdgeMesh::tuple_from_id(const PrimitiveType type, const long gid) const { + throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); if (type != PrimitiveType::Vertex) { throw std::runtime_error("Tuple switch: Invalid primitive type"); } From d4126493777b51e4ac62a2621e914b1695308919 Mon Sep 17 00:00:00 2001 From: zhouyuan chen <867442167@qq.com> Date: Fri, 22 Sep 2023 17:34:20 -0400 Subject: [PATCH 04/49] implemented some EdgeMesh functions --- src/wmtk/EdgeMesh.cpp | 184 +++++++++++++++++++++------ src/wmtk/EdgeMesh.hpp | 32 ++++- src/wmtk/TriMesh.cpp | 12 +- src/wmtk/Types.hpp | 5 +- src/wmtk/attribute/ConstAccessor.hpp | 5 +- 5 files changed, 186 insertions(+), 52 deletions(-) diff --git a/src/wmtk/EdgeMesh.cpp b/src/wmtk/EdgeMesh.cpp index b1275cae5a..fab3aa8995 100644 --- a/src/wmtk/EdgeMesh.cpp +++ b/src/wmtk/EdgeMesh.cpp @@ -1,63 +1,139 @@ #include "EdgeMesh.hpp" namespace wmtk { -Tuple EdgeMesh::vertex_tuple_from_id(long id) const -{ - throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); - return Tuple(-1, -1, -1, id, get_cell_hash_slow(id)); -} - EdgeMesh::EdgeMesh() - : Mesh(0) + : Mesh(1) + , m_ve_handle(register_attribute("m_ve", PrimitiveType::Vertex, 1)) + , m_ev_handle(register_attribute("m_ev", PrimitiveType::Edge, 2)) + , m_ee_handle(register_attribute("m_ee", PrimitiveType::Edge, 2)) {} +EdgeMesh::EdgeMesh(EdgeMesh&& o) = default; +EdgeMesh& EdgeMesh::operator=(const EdgeMesh& o) = default; +EdgeMesh& EdgeMesh::operator=(EdgeMesh&& o) = default; - -EdgeMesh::EdgeMesh(long size) - : EdgeMesh() +Tuple EdgeMesh::tuple_from_id(const PrimitiveType type, const long gid) const { - initialize(size); + throw std::runtime_error("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); + switch (type) { + case PrimitiveType::Vertex: { + return vertex_tuple_from_id(gid); + } + case PrimitiveType::Edge: { + return edge_tuple_from_id(gid); + } + case PrimitiveType::Face: { + throw std::runtime_error("no face tuple supported for edgemesh"); + break; + } + case PrimitiveType::Tetrahedron: { + throw std::runtime_error("no tet tuple supported for edgemesh"); + break; + } + default: throw std::runtime_error("Invalid primitive type"); break; + } } Tuple EdgeMesh::switch_tuple(const Tuple& tuple, PrimitiveType type) const { - throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); - throw std::runtime_error("Tuple switch: Invalid primitive type"); - return tuple; + throw std::runtime_error("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); + assert(is_valid_slow(tuple)); + bool ccw = is_ccw(tuple); + + // + switch (type) { + case PrimitiveType::Vertex: + return Tuple( + (tuple.m_local_vid + 1) % (long)2, + tuple.m_local_eid, + tuple.m_local_fid, + tuple.m_global_cid, + tuple.m_hash); + case PrimitiveType::Edge: + // don't know what is the result of the edge's switch, thought we just need vertex_switch? + case PrimitiveType::Face: + case PrimitiveType::Tetrahedron: + default: throw std::runtime_error("Tuple switch: Invalid primitive type"); break; + } } bool EdgeMesh::is_ccw(const Tuple&) const { - throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); - // trivial orientation so nothing can happen + throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); + // we don't need the oriented edge, so it should always be true return true; } -bool EdgeMesh::is_boundary(const Tuple&) const +bool EdgeMesh::is_boundary(const Tuple& tuple) const { - throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); - // every point is on the interior as it has no boundary simplices - return false; + throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); + assert(is_valid_slow(tuple)); + // fix an edge and a vertex, then compute the neighbour edge + ConstAccessor ee_accessor = create_const_accessor(m_ee_handle); + return ee_accessor.vector_attribute(tuple)(tuple.m_local_vid) < 0; } -bool EdgeMesh::is_boundary_vertex(const Tuple&) const +bool EdgeMesh::is_boundary_vertex(const Tuple& tuple) const { throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); - // every point is on the interior as it has no boundary simplices + // boudnary_vertex is a vertex with only one degree + assert(is_valid_slow(tuple)); + ConstAccessor ve_accessor = create_const_accessor(m_ve_handle); + // not sure if it works. + // I think the main problem is I still not sure about the mechanisim of the "id" and "e_tuple" + // funtions. + auto e = ve_accessor.index_access().scalar_attribute(tuple.m_local_vid); + ConstAccessor ev_accessor = create_const_accessor(m_ev_handle); + auto ev = ev_accessor.index_access().vector_attribute(e); + // tuple_from_id(,); return false; } -void EdgeMesh::initialize(long count) +void EdgeMesh::initialize( + Eigen::Ref EV, + Eigen::Ref EE, + Eigen::Ref VE) { throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); - set_capacities({count}); - reserve_attributes_to_fit(); + std::vector cap{ + static_cast(EV.rows()), + static_cast(EE.rows()), + static_cast(VE.rows())}; + + set_capacities(cap); + + // get Accessors for topology + Accessor ev_accessor = create_accessor(m_ev_handle); + Accessor ve_accessor = create_accessor(m_ve_handle); + Accessor ee_accessor = create_accessor(m_ee_handle); + Accessor v_flag_accessor = get_flag_accessor(PrimitiveType::Vertex); - for (long i = 0; i < capacity(PrimitiveType::Vertex); ++i) { - v_flag_accessor.index_access().scalar_attribute(i) |= 0x1; - } + Accessor e_flag_accessor = get_flag_accessor(PrimitiveType::Edge); + + // wait to add + // ... + + // iterate over the matrices and fill attributes + // for (long i = 0; i < capacity(PrimitiveType::Face); ++i) { + // ev_accessor.index_access().vector_attribute(i) = EV.row(i).transpose(); + // ve_accessor.index_access().vector_attribute(i) = VE.row(i).transpose(); + // ee_accessor.index_access().vector_attribute(i) = EE.row(i).transpose(); + + // f_flag_accessor.index_access().scalar_attribute(i) |= 0x1; + // } + // // m_ve + // for (long i = 0; i < capacity(PrimitiveType::Vertex); ++i) { + // ve_accessor.index_access().scalar_attribute(i) = VE(i); + // v_flag_accessor.index_access().scalar_attribute(i) |= 0x1; + // } + // // m_ve + // for (long i = 0; i < capacity(PrimitiveType::Edge); ++i) { + // ev_accessor.index_access().scalar_attribute(i) = EV(i); + // e_flag_accessor.index_access().scalar_attribute(i) |= 0x1; + // } } bool EdgeMesh::is_valid(const Tuple& tuple, ConstAccessor& hash_accessor) const { throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); + // copied from PointMesh.cpp if (tuple.is_null()) return false; return true; return Mesh::is_hash_valid(tuple, hash_accessor); @@ -65,22 +141,56 @@ bool EdgeMesh::is_valid(const Tuple& tuple, ConstAccessor& hash_accessor) long EdgeMesh::id(const Tuple& tuple, PrimitiveType type) const { - throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); + throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); switch (type) { - case PrimitiveType::Vertex: return tuple.m_global_cid; - case PrimitiveType::Edge: + case PrimitiveType::Vertex: { + ConstAccessor ev_accessor = create_const_accessor(m_ev_handle); + auto ev = ev_accessor.vector_attribute(tuple); + return ev(tuple.m_local_vid); + } + case PrimitiveType::Edge: { + return tuple.m_global_cid; + } case PrimitiveType::Face: case PrimitiveType::Tetrahedron: - default: throw std::runtime_error("Tuple switch: Invalid primitive type"); break; + default: throw std::runtime_error("Tuple id: Invalid primitive type"); } } -Tuple EdgeMesh::tuple_from_id(const PrimitiveType type, const long gid) const +Tuple EdgeMesh::vertex_tuple_from_id(long id) const { - throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); - if (type != PrimitiveType::Vertex) { - throw std::runtime_error("Tuple switch: Invalid primitive type"); + throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); + ConstAccessor ve_accessor = create_const_accessor(m_ve_handle); + // confused about this "id", does this mean the id of vertex or the edge? I refer to the + // TriMesh.cpp(from line 243) + auto e = ve_accessor.index_access().scalar_attribute(id); + ConstAccessor ev_accessor = create_const_accessor(m_ev_handle); + auto ev = ev_accessor.index_access().vector_attribute(e); + for (long i = 0; i < 2; ++i) { + if (ev(i) == id) { + assert(autogen::auto_2d_table_complete_vertex[i][0] == i); + // do not know if I use this function right. + Tuple v_tuple = Tuple( + i, + -1, + -1, + e, + get_cell_hash_slow( + e)); // TODO replace by function that takes hash accessor as parameter + assert(is_ccw(v_tuple)); // is_ccw also checks for validity + return v_tuple; + } } - return vertex_tuple_from_id(gid); + throw std::runtime_error("vertex_tuple_from_id failed"); +} + +Tuple EdgeMesh::edge_tuple_from_id(long id) const +{ + throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); + Tuple e_tuple = Tuple(-1, -1, -1, id, get_cell_hash_slow(id)); + assert(is_ccw(e_tuple)); + assert(is_valid_slow(e_tuple)); + return e_tuple; + throw std::runtime_error("edge_tuple_from_id failed"); } } // namespace wmtk diff --git a/src/wmtk/EdgeMesh.hpp b/src/wmtk/EdgeMesh.hpp index f0b471087d..67228dfd2d 100644 --- a/src/wmtk/EdgeMesh.hpp +++ b/src/wmtk/EdgeMesh.hpp @@ -10,14 +10,18 @@ namespace wmtk { // topologies class EdgeMesh : public Mesh { -private: - Tuple vertex_tuple_from_id(long id) const; - public: EdgeMesh(); - EdgeMesh(long size); + EdgeMesh(EdgeMesh&& o); + EdgeMesh& operator=(const EdgeMesh& o); + EdgeMesh& operator=(EdgeMesh&& o); + + void initialize( + Eigen::Ref EV, + Eigen::Ref EE, + Eigen::Ref VE); - PrimitiveType top_simplex_type() const override { return PrimitiveType::Vertex; } + PrimitiveType top_simplex_type() const override { return PrimitiveType::Edge; } Tuple switch_tuple(const Tuple& tuple, PrimitiveType type) const override; bool is_ccw(const Tuple& tuple) const override; bool is_boundary(const Tuple& tuple) const override; @@ -25,17 +29,21 @@ class EdgeMesh : public Mesh // TODO: should just write is_boundary(PrimitiveType) bool is_boundary_edge(const Tuple& tuple) const override { return true; } - void initialize(long count); - bool is_valid(const Tuple& tuple, ConstAccessor& hash_accessor) const override; + Tuple edge_tuple_from_id(long id) const; + Tuple vertex_tuple_from_id(long id) const; + Tuple split_edge(const Tuple&, Accessor&) override { return {}; } Tuple collapse_edge(const Tuple&, Accessor&) override { return {}; } bool is_connectivity_valid() const override { return true; } protected: long id(const Tuple& tuple, PrimitiveType type) const override; + long id(const Simplex& simplex) const { return id(simplex.tuple(), simplex.primitive_type()); } + long id_vertex(const Tuple& tuple) const { return id(tuple, PrimitiveType::Vertex); } + long id_edge(const Tuple& tuple) const { return id(tuple, PrimitiveType::Edge); } /** * @brief internal function that returns the tuple of requested type, and has the global index @@ -45,6 +53,16 @@ class EdgeMesh : public Mesh * @return Tuple */ Tuple tuple_from_id(const PrimitiveType type, const long gid) const override; + + // internal structure that encapsulations the actual execution of split and collapse + class TriMeshOperationExecutor; + static Tuple with_different_cid(const Tuple& t, long cid); + + + // not sure if it is needed + attribute::MeshAttributeHandle m_ve_handle; + attribute::MeshAttributeHandle m_ev_handle; + attribute::MeshAttributeHandle m_ee_handle; // record relationship between edges }; } // namespace wmtk diff --git a/src/wmtk/TriMesh.cpp b/src/wmtk/TriMesh.cpp index 4ad5330a7d..1a9d847c45 100644 --- a/src/wmtk/TriMesh.cpp +++ b/src/wmtk/TriMesh.cpp @@ -337,7 +337,8 @@ bool TriMesh::is_connectivity_valid() const } int cnt = 0; for (long j = 0; j < 3; ++j) { - if (fe_accessor.index_access().vector_attribute(ef_accessor.index_access().scalar_attribute(i))[j] == i) { + if (fe_accessor.index_access().vector_attribute( + ef_accessor.index_access().scalar_attribute(i))[j] == i) { cnt++; } } @@ -355,7 +356,8 @@ bool TriMesh::is_connectivity_valid() const } int cnt = 0; for (long j = 0; j < 3; ++j) { - if (fv_accessor.index_access().vector_attribute(vf_accessor.index_access().scalar_attribute(i))[j] == i) { + if (fv_accessor.index_access().vector_attribute( + vf_accessor.index_access().scalar_attribute(i))[j] == i) { cnt++; } } @@ -374,7 +376,8 @@ bool TriMesh::is_connectivity_valid() const for (long j = 0; j < 3; ++j) { long nb = ff_accessor.index_access().vector_attribute(i)[j]; if (nb == -1) { - if (ef_accessor.index_access().const_scalar_attribute(fe_accessor.index_access().const_vector_attribute(i)[j]) != i) { + if (ef_accessor.index_access().const_scalar_attribute( + fe_accessor.index_access().const_vector_attribute(i)[j]) != i) { // std::cout << "FF and FE not compatible" << std::endl; return false; } @@ -395,7 +398,8 @@ bool TriMesh::is_connectivity_valid() const return false; } - if (fe_accessor.index_access().const_vector_attribute(i)[j] != fe_accessor.index_access().const_vector_attribute(nb)[id_in_nb]) { + if (fe_accessor.index_access().const_vector_attribute(i)[j] != + fe_accessor.index_access().const_vector_attribute(nb)[id_in_nb]) { // std::cout << "FF and FE not compatible" << std::endl; return false; } diff --git a/src/wmtk/Types.hpp b/src/wmtk/Types.hpp index 043a5c782f..eae2e90444 100644 --- a/src/wmtk/Types.hpp +++ b/src/wmtk/Types.hpp @@ -4,13 +4,14 @@ namespace wmtk { using RowVectors3l = Eigen::Matrix; +using RowVectors2l = Eigen::Matrix; using VectorXl = Eigen::Matrix; using RowVectors4l = Eigen::Matrix; using RowVectors6l = Eigen::Matrix; using RowVectors3d = Eigen::Matrix; template -using Vector = Eigen::Matrix; +using Vector = Eigen::Matrix; template -using VectorX = Vector; +using VectorX = Vector; } // namespace wmtk diff --git a/src/wmtk/attribute/ConstAccessor.hpp b/src/wmtk/attribute/ConstAccessor.hpp index 3b8d7bc2ea..752e87d5ae 100644 --- a/src/wmtk/attribute/ConstAccessor.hpp +++ b/src/wmtk/attribute/ConstAccessor.hpp @@ -18,6 +18,7 @@ class ConstAccessor : protected TupleAccessor friend class wmtk::Mesh; friend class wmtk::TetMesh; friend class wmtk::TriMesh; + friend class wmtk::EdgeMesh; friend class wmtk::PointMesh; friend class wmtk::TriMeshOperationExecutor; using Scalar = T; @@ -51,12 +52,12 @@ class ConstAccessor : protected TupleAccessor using BaseType::attribute; // access to Attribute object being used here // shows the depth of scope stacks if they exist, mostly for debug - using CachingBaseType::stack_depth; using CachingBaseType::has_stack; + using CachingBaseType::stack_depth; protected: - using TupleBaseType::caching_base_type; using TupleBaseType::base_type; + using TupleBaseType::caching_base_type; using TupleBaseType::scalar_attribute; using TupleBaseType::vector_attribute; From 96325c630c38c856893b73024820c1f5bef6c43d Mon Sep 17 00:00:00 2001 From: zhouyuan chen <867442167@qq.com> Date: Tue, 26 Sep 2023 11:45:24 -0400 Subject: [PATCH 05/49] add EdgeMeshOperationExecutor and DEBUG_EdgeMesh --- src/wmtk/CMakeLists.txt | 2 + src/wmtk/EdgeMesh.cpp | 33 +-- src/wmtk/EdgeMesh.hpp | 3 +- src/wmtk/EdgeMeshOperationExecutor.cpp | 389 +++++++++++++++++++++++++ src/wmtk/EdgeMeshOperationExecutor.hpp | 65 +++++ src/wmtk/Tuple.hpp | 2 +- tests/CMakeLists.txt | 2 + tests/tools/DEBUG_EdgeMesh.cpp | 128 ++++++++ tests/tools/DEBUG_EdgeMesh.hpp | 67 +++++ 9 files changed, 670 insertions(+), 21 deletions(-) create mode 100644 src/wmtk/EdgeMeshOperationExecutor.cpp create mode 100644 src/wmtk/EdgeMeshOperationExecutor.hpp create mode 100644 tests/tools/DEBUG_EdgeMesh.cpp create mode 100644 tests/tools/DEBUG_EdgeMesh.hpp diff --git a/src/wmtk/CMakeLists.txt b/src/wmtk/CMakeLists.txt index 391bcb4538..ce4de97f5e 100644 --- a/src/wmtk/CMakeLists.txt +++ b/src/wmtk/CMakeLists.txt @@ -11,6 +11,8 @@ set(SRC_FILES TriMesh.hpp TetMesh.cpp TetMesh.hpp + EdgeMeshOperationExecutor.hpp + EdgeMeshOperationExecutor.cpp TriMeshOperationExecutor.hpp TriMeshOperationExecutor.cpp TetMeshOperationExecutor.hpp diff --git a/src/wmtk/EdgeMesh.cpp b/src/wmtk/EdgeMesh.cpp index fab3aa8995..3486ed492b 100644 --- a/src/wmtk/EdgeMesh.cpp +++ b/src/wmtk/EdgeMesh.cpp @@ -6,6 +6,7 @@ EdgeMesh::EdgeMesh() , m_ev_handle(register_attribute("m_ev", PrimitiveType::Edge, 2)) , m_ee_handle(register_attribute("m_ee", PrimitiveType::Edge, 2)) {} +// EdgeMesh::EdgeMesh(const EdgeMesh&& o) = default; EdgeMesh::EdgeMesh(EdgeMesh&& o) = default; EdgeMesh& EdgeMesh::operator=(const EdgeMesh& o) = default; EdgeMesh& EdgeMesh::operator=(EdgeMesh&& o) = default; @@ -90,7 +91,7 @@ void EdgeMesh::initialize( Eigen::Ref EE, Eigen::Ref VE) { - throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); + throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); std::vector cap{ static_cast(EV.rows()), static_cast(EE.rows()), @@ -108,25 +109,19 @@ void EdgeMesh::initialize( // wait to add // ... - // iterate over the matrices and fill attributes - // for (long i = 0; i < capacity(PrimitiveType::Face); ++i) { - // ev_accessor.index_access().vector_attribute(i) = EV.row(i).transpose(); - // ve_accessor.index_access().vector_attribute(i) = VE.row(i).transpose(); - // ee_accessor.index_access().vector_attribute(i) = EE.row(i).transpose(); - - // f_flag_accessor.index_access().scalar_attribute(i) |= 0x1; - // } - // // m_ve - // for (long i = 0; i < capacity(PrimitiveType::Vertex); ++i) { - // ve_accessor.index_access().scalar_attribute(i) = VE(i); - // v_flag_accessor.index_access().scalar_attribute(i) |= 0x1; - // } - // // m_ve - // for (long i = 0; i < capacity(PrimitiveType::Edge); ++i) { - // ev_accessor.index_access().scalar_attribute(i) = EV(i); - // e_flag_accessor.index_access().scalar_attribute(i) |= 0x1; - // } + for (long i = 0; i < capacity(PrimitiveType::Edge); ++i) { + ev_accessor.index_access().vector_attribute(i) = EV.row(i).transpose(); + ee_accessor.index_access().vector_attribute(i) = EE.row(i).transpose(); + + e_flag_accessor.index_access().scalar_attribute(i) |= 0x1; + } + + // m_vf + for (long i = 0; i < capacity(PrimitiveType::Vertex); ++i) { + ve_accessor.index_access().scalar_attribute(i) = VE(i); + e_flag_accessor.index_access().scalar_attribute(i) |= 0x1; + } } diff --git a/src/wmtk/EdgeMesh.hpp b/src/wmtk/EdgeMesh.hpp index 67228dfd2d..201e267962 100644 --- a/src/wmtk/EdgeMesh.hpp +++ b/src/wmtk/EdgeMesh.hpp @@ -12,6 +12,7 @@ class EdgeMesh : public Mesh { public: EdgeMesh(); + // EdgeMesh(const EdgeMesh&& o); EdgeMesh(EdgeMesh&& o); EdgeMesh& operator=(const EdgeMesh& o); EdgeMesh& operator=(EdgeMesh&& o); @@ -55,7 +56,7 @@ class EdgeMesh : public Mesh Tuple tuple_from_id(const PrimitiveType type, const long gid) const override; // internal structure that encapsulations the actual execution of split and collapse - class TriMeshOperationExecutor; + class EdgeMeshOperationExecutor; static Tuple with_different_cid(const Tuple& t, long cid); diff --git a/src/wmtk/EdgeMeshOperationExecutor.cpp b/src/wmtk/EdgeMeshOperationExecutor.cpp new file mode 100644 index 0000000000..673304c562 --- /dev/null +++ b/src/wmtk/EdgeMeshOperationExecutor.cpp @@ -0,0 +1,389 @@ + +#include "EdgeMeshOperationExecutor.hpp" + +namespace wmtk { +// constructor +EdgeMesh::EdgeMeshOperationExecutor::EdgeMeshOperationExecutor( + EdgeMesh& m, + const Tuple& operating_tuple, + Accessor& hash_acc) + : flag_accessors{{m.get_flag_accessor(PrimitiveType::Vertex), m.get_flag_accessor(PrimitiveType::Edge)}} + , ee_accessor(m.create_accessor(m.m_ee_handle)) + , ev_accessor(m.create_accessor(m.m_ev_handle)) + , ve_accessor(m.create_accessor(m.m_ve_handle)) + , hash_accessor(hash_acc) + , m_mesh(m) + , m_operating_tuple(operating_tuple) + +{ + // store ids of edge and incident vertices + m_operating_edge_id = m_mesh.id_edge(m_operating_tuple); + m_spine_vids[0] = m_mesh.id_vertex(m_operating_tuple); + m_spine_vids[1] = m_mesh.id_vertex(m_mesh.switch_vertex(m_operating_tuple)); + + const SimplicialComplex edge_closed_star = + SimplicialComplex::closed_star(m_mesh, Simplex::edge(operating_tuple)); + + // get all faces incident to the edge + for (const Simplex& f : edge_closed_star.get_faces()) { + // m_incident_face_datas.emplace_back(get_incident_face_data(f.tuple())); + } + + // update hash on all faces in the two-ring neighborhood + SimplicialComplex hash_update_region(m); + for (const Simplex& v : edge_closed_star.get_vertices()) { + const SimplicialComplex v_closed_star = SimplicialComplex::closed_star(m_mesh, v); + hash_update_region.unify_with_complex(v_closed_star); + } + for (const Simplex& f : hash_update_region.get_faces()) { + cell_ids_to_update_hash.push_back(m_mesh.id(f)); + } +} + +void EdgeMesh::EdgeMeshOperationExecutor::delete_simplices() +{ + for (size_t d = 0; d < simplex_ids_to_delete.size(); ++d) { + for (const long id : simplex_ids_to_delete[d]) { + flag_accessors[d].index_access().scalar_attribute(id) = 0; + } + } +} + +void EdgeMesh::EdgeMeshOperationExecutor::update_cell_hash() +{ + m_mesh.update_cell_hashes(cell_ids_to_update_hash, hash_accessor); +} + +const std::array, 3> +EdgeMesh::EdgeMeshOperationExecutor::get_split_simplices_to_delete( + const Tuple& tuple, + const EdgeMesh& m) +{ + const SimplicialComplex sc = SimplicialComplex::open_star(m, Simplex::edge(tuple)); + std::array, 3> ids; + for (const Simplex& s : sc.get_simplices()) { + ids[get_simplex_dimension(s.primitive_type())].emplace_back(m.id(s)); + } + + return ids; +} + +const std::array, 3> +EdgeMesh::EdgeMeshOperationExecutor::get_collapse_simplices_to_delete( + const Tuple& tuple, + const EdgeMesh& m) +{ + const SimplicialComplex vertex_open_star = + SimplicialComplex::open_star(m, Simplex::vertex(tuple)); + const SimplicialComplex edge_closed_star = + SimplicialComplex::closed_star(m, Simplex::edge(tuple)); + + const SimplicialComplex sc = + SimplicialComplex::get_intersection(vertex_open_star, edge_closed_star); + + std::array, 3> ids; + for (const Simplex& s : sc.get_simplices()) { + ids[get_simplex_dimension(s.primitive_type())].emplace_back(m.id(s)); + } + + return ids; +} + +std::vector> +EdgeMesh::EdgeMeshOperationExecutor::prepare_operating_tuples_for_child_meshes() const +{ + std::vector> vec_t_child(m_incident_face_datas.size()); + for (long i = 0; i < long(m_incident_face_datas.size()); ++i) { + vec_t_child[i] = MultiMeshManager::map_edge_tuple_to_all_children( + m_mesh, + m_incident_face_datas[i].local_operating_tuple); + } + // clean up redundant + if (m_incident_face_datas.size() > 1) { + for (long j = 0; j < long(vec_t_child[1].size()); ++j) { + auto child_mesh_ptr = m_mesh.multi_mesh_manager.child_meshes[j]; + if (vec_t_child[1][j].is_null() || vec_t_child[0][j].is_null()) { + continue; + } + if (child_mesh_ptr->simplices_are_equal( + Simplex::edge(vec_t_child[0][j]), + Simplex::edge(vec_t_child[1][j]))) { + vec_t_child[1][j] = Tuple(); // redundant, set as null tuple + } + } + } + return vec_t_child; +} + +Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge() +{ + if (!m_mesh.multi_mesh_manager.is_parent_mesh()) { + return split_edge_single_mesh(); + } else { + std::vector> vec_t_child = prepare_operating_tuples_for_child_meshes(); + + // do split on parent_mesh + Tuple ret_tuple = split_edge_single_mesh(); + + for (auto child_mesh_ptr : m_mesh.multi_mesh_manager.child_meshes) { + long child_id = child_mesh_ptr->multi_mesh_manager.child_id(); + if (child_mesh_ptr->top_simplex_type() == PrimitiveType::Face) { + // this child_mesh is a EdgeMesh + EdgeMesh& child_tri_mesh = *std::static_pointer_cast(child_mesh_ptr); + + std::vector> child_new_cell_ids; + for (long i = 0; i < long(m_incident_face_datas.size()); ++i) { + Tuple t_child = vec_t_child[i][child_id]; + if (t_child.is_null()) { + if (child_new_cell_ids.size() <= i) child_new_cell_ids.emplace_back(-1, -1); + continue; + } + auto child_hash_acc = child_tri_mesh.get_cell_hash_accessor(); + EdgeMesh::EdgeMeshOperationExecutor executor_child( + child_tri_mesh, + t_child, + child_hash_acc); + executor_child.split_edge(); + for (auto child_incident_face_data : executor_child.m_incident_face_datas) { + child_new_cell_ids.emplace_back( + child_incident_face_data.split_f0, + child_incident_face_data.split_f1); + } + } + + assert(child_new_cell_ids.size() == m_incident_face_datas.size()); + + // update_hash on new cells + for (long i = 0; i < long(m_incident_face_datas.size()); i++) { + const auto& split_fs_child = child_new_cell_ids[i]; + long split_f0_child = split_fs_child.first; + long split_f1_child = split_fs_child.second; + + const auto& incident_face_data = m_incident_face_datas[i]; + long split_f0_parent = incident_face_data.split_f0; + long split_f1_parent = incident_face_data.split_f1; + + Tuple tuple_child = (split_f0_child == -1) + ? Tuple() + : child_tri_mesh.face_tuple_from_id(split_f0_child); + Tuple tuple_parent = m_mesh.face_tuple_from_id(split_f0_parent); + + if (!tuple_child.is_null()) { + MultiMeshManager::write_tuple_map_attribute( + child_tri_mesh.multi_mesh_manager.map_to_parent_handle, + child_tri_mesh, + tuple_child, + tuple_parent); + } + MultiMeshManager::write_tuple_map_attribute( + m_mesh.multi_mesh_manager.map_to_child_handles[child_id], + m_mesh, + tuple_parent, + tuple_child); + + tuple_child = (split_f1_child == -1) + ? Tuple() + : child_tri_mesh.face_tuple_from_id(split_f1_child); + tuple_parent = m_mesh.face_tuple_from_id(split_f1_parent); + if (!tuple_child.is_null()) { + MultiMeshManager::write_tuple_map_attribute( + child_tri_mesh.multi_mesh_manager.map_to_parent_handle, + child_tri_mesh, + tuple_child, + tuple_parent); + } + MultiMeshManager::write_tuple_map_attribute( + m_mesh.multi_mesh_manager.map_to_child_handles[child_id], + m_mesh, + tuple_parent, + tuple_child); + } + + // update_hash on neighboring cells + update_hash_in_map(child_tri_mesh); + } + } + return ret_tuple; + } +} + +Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge_single_mesh() +{ + simplex_ids_to_delete = get_split_simplices_to_delete(m_operating_tuple, m_mesh); + + // create new vertex (center) + std::vector new_vids = this->request_simplex_indices(PrimitiveType::Vertex, 1); + assert(new_vids.size() == 1); + const long v_new = new_vids[0]; + + // create new edges (spine) + std::vector new_eids = this->request_simplex_indices(PrimitiveType::Edge, 2); + assert(new_eids.size() == 2); + + for (IncidentFaceData& face_data : m_incident_face_datas) { + replace_incident_face(v_new, new_eids, face_data); + } + assert(m_incident_face_datas.size() <= 2); + if (m_incident_face_datas.size() > 1) { + connect_faces_across_spine(); + } + + update_cell_hash(); + delete_simplices(); + // return Tuple new_fid, new_vid that points + const long new_tuple_fid = m_incident_face_datas[0].split_f1; + Tuple ret = m_mesh.edge_tuple_from_id(new_eids[1]); + if (m_mesh.id_vertex(ret) != v_new) { + ret = m_mesh.switch_vertex(ret); + } + if (m_mesh.id_face(ret) != new_tuple_fid) { + ret = m_mesh.switch_face(ret); + } + assert(m_mesh.is_valid_slow(ret)); + + return ret; + // return m_mesh.with_different_cid(m_operating_tuple, m_incident_face_datas[0].split_f0); +} + +void EdgeMesh::EdgeMeshOperationExecutor::update_hash_in_map(EdgeMesh& child_mesh) +{ + long child_id = child_mesh.multi_mesh_manager.child_id(); + auto child_hash_accessor = child_mesh.get_cell_hash_accessor(); + + for (auto parent_cell_id : cell_ids_to_update_hash) { + auto [t_parent_old, t_child_old] = MultiMeshManager::read_tuple_map_attribute( + m_mesh.multi_mesh_manager.map_to_child_handles[child_id], + m_mesh, + m_mesh.tuple_from_id(m_mesh.top_simplex_type(), parent_cell_id)); + + long parent_cell_hash = m_mesh.get_cell_hash_slow(parent_cell_id); + Tuple t_parent_new = t_parent_old.with_updated_hash(parent_cell_hash); + + if (t_child_old.is_null()) { + MultiMeshManager::write_tuple_map_attribute( + m_mesh.multi_mesh_manager.map_to_child_handles[child_id], + m_mesh, + t_parent_new, + Tuple()); + } else { + long child_cell_hash = + child_hash_accessor.index_access().const_scalar_attribute(t_child_old.m_global_cid); + Tuple t_child_new = t_child_old.with_updated_hash(child_cell_hash); + MultiMeshManager::write_tuple_map_attribute( + m_mesh.multi_mesh_manager.map_to_child_handles[child_id], + m_mesh, + t_parent_new, + t_child_new); + + MultiMeshManager::write_tuple_map_attribute( + child_mesh.multi_mesh_manager.map_to_parent_handle, + child_mesh, + t_child_new, + t_parent_new); + } + } +} + +Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge() +{ + if (!m_mesh.multi_mesh_manager.is_parent_mesh()) { + return collapse_edge_single_mesh(); + } else { + std::vector> vec_t_child = prepare_operating_tuples_for_child_meshes(); + + // do collapse on parent_mesh + Tuple ret_tuple = collapse_edge_single_mesh(); + + for (auto child_mesh_ptr : m_mesh.multi_mesh_manager.child_meshes) { + long child_id = child_mesh_ptr->multi_mesh_manager.child_id(); + + if (child_mesh_ptr->top_simplex_type() == PrimitiveType::Face) { + // this child_mesh is a EdgeMesh + EdgeMesh& child_tri_mesh = *std::static_pointer_cast(child_mesh_ptr); + + for (long i = 0; i < long(m_incident_face_datas.size()); ++i) { + Tuple t_child = vec_t_child[i][child_id]; + if (t_child.is_null()) { + continue; + } + auto child_hash_acc = child_tri_mesh.get_cell_hash_accessor(); + EdgeMesh::EdgeMeshOperationExecutor executor_child( + child_tri_mesh, + t_child, + child_hash_acc); + executor_child.collapse_edge(); + } + // update_hash + update_hash_in_map(child_tri_mesh); + } + } + + return ret_tuple; + } +} + + +Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge_single_mesh() +{ + simplex_ids_to_delete = get_collapse_simplices_to_delete(m_operating_tuple, m_mesh); + + // must collect star before changing connectivity + const SimplicialComplex v0_star = + SimplicialComplex::closed_star(m_mesh, Simplex::vertex(m_operating_tuple)); + + + connect_ears(); + + const long& v0 = m_spine_vids[0]; + const long& v1 = m_spine_vids[1]; + + // replace v0 by v1 in incident faces + for (const Simplex& f : v0_star.get_faces()) { + const long fid = m_mesh.id(f); + auto fv = fv_accessor.index_access().vector_attribute(fid); + for (long i = 0; i < 3; ++i) { + if (fv[i] == v0) { + fv[i] = v1; + break; + } + } + } + + const long& ret_eid = m_incident_face_datas[0].ears[1].eid; + const long& ret_vid = m_spine_vids[1]; + const long& ef0 = m_incident_face_datas[0].ears[0].fid; + const long& ef1 = m_incident_face_datas[0].ears[1].fid; + + const long new_tuple_fid = (ef0 > -1) ? ef0 : ef1; + + update_cell_hash(); + delete_simplices(); + + Tuple ret = m_mesh.edge_tuple_from_id(ret_eid); + if (m_mesh.id_vertex(ret) != ret_vid) { + ret = m_mesh.switch_vertex(ret); + } + assert(m_mesh.id_vertex(ret) == ret_vid); + if (m_mesh.id_face(ret) != new_tuple_fid) { + ret = m_mesh.switch_face(ret); + } + assert(m_mesh.id_face(ret) == new_tuple_fid); + assert(m_mesh.is_valid_slow(ret)); + + + return ret; + + // return a ccw tuple from left ear if it exists, otherwise return a ccw tuple from right ear + // return m_mesh.tuple_from_id(PrimitiveType::Vertex, v1); +} + +std::vector EdgeMesh::EdgeMeshOperationExecutor::request_simplex_indices( + const PrimitiveType type, + long count) +{ + m_mesh.reserve_attributes(type, m_mesh.capacity(type) + count); + + return m_mesh.request_simplex_indices(type, count); +} + +} // namespace wmtk diff --git a/src/wmtk/EdgeMeshOperationExecutor.hpp b/src/wmtk/EdgeMeshOperationExecutor.hpp new file mode 100644 index 0000000000..1e4656f7a4 --- /dev/null +++ b/src/wmtk/EdgeMeshOperationExecutor.hpp @@ -0,0 +1,65 @@ +#pragma once +#include +#include "EdgeMesh.hpp" +#include "SimplicialComplex.hpp" +#include "Tuple.hpp" +namespace wmtk { +class EdgeMesh::EdgeMeshOperationExecutor +{ +public: + EdgeMeshOperationExecutor(EdgeMesh& m, const Tuple& operating_tuple, Accessor& hash_acc); + void delete_simplices(); + void update_cell_hash(); + + std::array, 3> flag_accessors; + Accessor ee_accessor; + Accessor ev_accessor; + Accessor ve_accessor; + Accessor& hash_accessor; + + /** + * @brief gather all simplices that are deleted in a split + * + * The deleted simplices are exactly the open star of the edge + */ + static const std::array, 3> get_split_simplices_to_delete( + const Tuple& tuple, + const EdgeMesh& m); + + /** + * @brief gather all simplices that are deleted in a collapse + * + * The deleted simplices are the intersection of the open star of the vertex and the closed star + * of the edge. This comes down to one vertex, three edges, and two faces if the edge is on the + * interior. On the boundary it is one vertex, two edges, and one face. + */ + static const std::array, 3> get_collapse_simplices_to_delete( + const Tuple& tuple, + const EdgeMesh& m); + + const std::array& incident_vids() const { return m_spine_vids; } + + long operating_edge_id() const { return m_operating_edge_id; } + + Tuple split_edge(); + Tuple collapse_edge(); + Tuple split_edge_single_mesh(); + Tuple collapse_edge_single_mesh(); + + std::vector request_simplex_indices(const PrimitiveType type, long count); + + std::array, 3> simplex_ids_to_delete; + std::vector cell_ids_to_update_hash; + EdgeMesh& m_mesh; + Tuple m_operating_tuple; + + +private: + std::vector> prepare_operating_tuples_for_child_meshes() const; + void update_hash_in_map(EdgeMesh& child_mesh); + + // common simplicies + std::array m_spine_vids; // V_A_id, V_B_id; + long m_operating_edge_id; +}; +} // namespace wmtk diff --git a/src/wmtk/Tuple.hpp b/src/wmtk/Tuple.hpp index 4832bbfb85..98d7ac3ebf 100644 --- a/src/wmtk/Tuple.hpp +++ b/src/wmtk/Tuple.hpp @@ -7,8 +7,8 @@ namespace wmtk { class Mesh; class PointMesh; -class EdgeMesh; class TriMesh; +class EdgeMesh; class TetMesh; namespace operations { class Operation; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 08a53809f1..ca1438a3a8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -24,6 +24,8 @@ set(TEST_SOURCES test_3d_operations.cpp test_multi_mesh.cpp tools/DEBUG_PointMesh.hpp + tools/DEBUG_EdgeMesh.hpp + tools/DEBUG_EdgeMesh.cpp tools/DEBUG_TriMesh.hpp tools/DEBUG_TriMesh.cpp tools/TriMesh_examples.hpp diff --git a/tests/tools/DEBUG_EdgeMesh.cpp b/tests/tools/DEBUG_EdgeMesh.cpp new file mode 100644 index 0000000000..621e71a042 --- /dev/null +++ b/tests/tools/DEBUG_EdgeMesh.cpp @@ -0,0 +1,128 @@ +#include "DEBUG_EdgeMesh.hpp" +#include + +namespace wmtk::tests { + +// DEBUG_EdgeMesh::DEBUG_EdgeMesh(const EdgeMesh& m) +// : EdgeMesh(m) +// {} +DEBUG_EdgeMesh::DEBUG_EdgeMesh(EdgeMesh&& m) + : EdgeMesh(std::move(m)) +{} + + +bool DEBUG_EdgeMesh::operator==(const DEBUG_EdgeMesh& o) const +{ + return static_cast(*this) == static_cast(o); +} +bool DEBUG_EdgeMesh::operator!=(const DEBUG_EdgeMesh& o) const +{ + return !(*this == o); +} + +void DEBUG_EdgeMesh::print_state() const {} + +void DEBUG_EdgeMesh::print_ve() const +{ + auto ev_accessor = create_base_accessor(e_handle(PrimitiveType::Vertex)); + auto e_flag_accessor = get_flag_accessor(PrimitiveType::Edge); + for (long id = 0; id < capacity(PrimitiveType::Edge); ++id) { + auto ev = ev_accessor.const_vector_attribute(id); + if (e_flag_accessor.const_scalar_attribute(tuple_from_id(PrimitiveType::Edge, id)) == 0) { + std::cout << "edge " << id << " is deleted" << std::endl; + } else { + std::cout << ev(0) << " " << ev(1) << std::endl; + } + } +} + +Eigen::Matrix DEBUG_EdgeMesh::ev_from_eid(const long eid) const +{ + auto ev_accessor = create_base_accessor(e_handle(PrimitiveType::Vertex)); + return ev_accessor.vector_attribute(eid); +} + +auto DEBUG_EdgeMesh::edge_tuple_from_vids(const long v1, const long v2) const -> Tuple +{ + ConstAccessor ev = create_accessor(m_ev_handle); + auto ev_base = create_base_accessor(m_ev_handle); + for (long eid = 0; eid < capacity(PrimitiveType::Edge); ++eid) { + Tuple edge = edge_tuple_from_id(eid); + auto ev0 = ev.const_vector_attribute(edge); + long local_vid1 = -1, local_vid2 = -1; + for (long i = 0; i < ev0.size(); ++i) { + if (ev0[i] == v1) { + local_vid1 = i; + } + if (ev0[i] == v2) { + local_vid2 = i; + } + } + if (local_vid1 != -1 && local_vid2 != -1) { + // unsure for this s function + // + // return Tuple( + // local_vid1, + // (3 - local_vid1 - local_vid2) % 3, + // -1, + // eid, + // get_cell_hash_slow(eid)); + } + } + return Tuple(); +} + +auto DEBUG_EdgeMesh::tuple_from_edge_id(const long eid) const -> Tuple +{ + return tuple_from_id(PrimitiveType::Edge, eid); +} + + +const MeshAttributeHandle& DEBUG_EdgeMesh::e_handle(const PrimitiveType type) const +{ + switch (type) { + case PrimitiveType::Vertex: return m_ev_handle; + case PrimitiveType::Edge: return m_ee_handle; + case PrimitiveType::Face:; + default: throw std::runtime_error("Invalid PrimitiveType"); + } +} + +const MeshAttributeHandle& DEBUG_EdgeMesh::ve_handle() const +{ + return m_ve_handle; +} + +const MeshAttributeHandle& DEBUG_EdgeMesh::ev_handle() const +{ + return m_ev_handle; +} + + +void DEBUG_EdgeMesh::reserve_attributes(PrimitiveType type, long size) +{ + Mesh::reserve_attributes(type, size); +} + + +long DEBUG_EdgeMesh::id(const Tuple& tuple, PrimitiveType type) const +{ + return EdgeMesh::id(tuple, type); +} +long DEBUG_EdgeMesh::id(const Simplex& s) const +{ + return id(s.tuple(), s.primitive_type()); +} +Accessor DEBUG_EdgeMesh::get_cell_hash_accessor() +{ + return EdgeMesh::get_cell_hash_accessor(); +} +/** + * @brief returns the EdgeMeshOperationExecutor + */ +auto DEBUG_EdgeMesh::get_tmoe(const Tuple& t, Accessor& hash_accessor) + -> EdgeMeshOperationExecutor +{ + return EdgeMeshOperationExecutor(*this, t, hash_accessor); +} +} // namespace wmtk::tests diff --git a/tests/tools/DEBUG_EdgeMesh.hpp b/tests/tools/DEBUG_EdgeMesh.hpp new file mode 100644 index 0000000000..ba87b7de35 --- /dev/null +++ b/tests/tools/DEBUG_EdgeMesh.hpp @@ -0,0 +1,67 @@ +#pragma once +#include +#include + +namespace wmtk::tests { +class DEBUG_EdgeMesh : public EdgeMesh +{ +public: + using EdgeMesh::EdgeMesh; + // DEBUG_EdgeMesh(const EdgeMesh& m); + DEBUG_EdgeMesh(EdgeMesh&& m); + using EdgeMesh::operator=; + + + bool operator==(const DEBUG_EdgeMesh& o) const; + bool operator!=(const DEBUG_EdgeMesh& o) const; + + // uses spdlog to print out a variety of information about the mesh + void print_state() const; + + void print_ve() const; + Eigen::Matrix ev_from_eid(const long eid) const; + + auto edge_tuple_from_vids(const long v1, const long v2) const -> Tuple; + auto tuple_from_edge_id(const long eid) const -> Tuple; + + template + attribute::AccessorBase create_base_accessor(const MeshAttributeHandle& handle) + { + return attribute::AccessorBase(*this, handle); + } + + template + attribute::AccessorBase create_const_base_accessor( + const MeshAttributeHandle& handle) const + { + return attribute::AccessorBase(const_cast(*this), handle); + } + template + attribute::AccessorBase create_base_accessor(const MeshAttributeHandle& handle) const + { + return create_const_base_accessor(handle); + } + + const MeshAttributeHandle& e_handle(const PrimitiveType type) const; + + const MeshAttributeHandle& ve_handle() const; + + const MeshAttributeHandle& ev_handle() const; + + + void reserve_attributes(PrimitiveType type, long size); + + + long id(const Tuple& tuple, PrimitiveType type) const override; + long id(const Simplex& s) const; + /** + * @brief returns the TriMeshOperationExecutor + */ + using EdgeMesh::tuple_from_id; + + Accessor get_cell_hash_accessor(); + + EdgeMeshOperationExecutor get_tmoe(const Tuple& t, Accessor& hash_accessor); +}; + +} // namespace wmtk::tests From b749faca6154bd95ef7ea4b733801b2c1c21f2ab Mon Sep 17 00:00:00 2001 From: zhouyuan chen <867442167@qq.com> Date: Tue, 26 Sep 2023 20:41:46 -0400 Subject: [PATCH 06/49] add EdgeMesh_example and test code --- src/wmtk/EdgeMesh.cpp | 64 ++++++- src/wmtk/EdgeMesh.hpp | 4 +- src/wmtk/EdgeMeshOperationExecutor.cpp | 232 +---------------------- src/wmtk/EdgeMeshOperationExecutor.hpp | 2 +- tests/CMakeLists.txt | 3 + tests/test_1d_operations.cpp | 29 +++ tests/test_2d_operation_construction.cpp | 1 - tests/tools/EdgeMesh_examples.cpp | 45 +++++ tests/tools/EdgeMesh_examples.hpp | 9 + 9 files changed, 155 insertions(+), 234 deletions(-) create mode 100644 tests/test_1d_operations.cpp create mode 100644 tests/tools/EdgeMesh_examples.cpp create mode 100644 tests/tools/EdgeMesh_examples.hpp diff --git a/src/wmtk/EdgeMesh.cpp b/src/wmtk/EdgeMesh.cpp index 3486ed492b..1d3ded9f05 100644 --- a/src/wmtk/EdgeMesh.cpp +++ b/src/wmtk/EdgeMesh.cpp @@ -86,10 +86,65 @@ bool EdgeMesh::is_boundary_vertex(const Tuple& tuple) const return false; } +void EdgeMesh::initialize(Eigen::Ref E) +{ + // resize the EE and VE + RowVectors2l EE; + RowVectors2l VE; + EE.resize(E.rows(), 2); + long max_vid = -1; + for (size_t i = 0; i < E.rows(); i++) { + EE(i, 0) = -1; + EE(i, 1) = -1; + max_vid = std::max(max_vid, E(i, 0)); + max_vid = std::max(max_vid, E(i, 1)); + } + VE.resize(max_vid + 1, 2); + for (size_t i = 0; i < VE.rows(); i++) { + VE(i, 0) = -1; + VE(i, 1) = -1; + } + + // compute VE + for (size_t i = 0; i < E.rows(); i++) { + long vid0, vid1; + vid0 = E(i, 0); + vid1 = E(i, 1); + if (VE(vid0, 0) == -1) { + VE(vid0, 0) = i; + } else if (VE(vid0, 1) == -1) { + VE(vid0, 1) = i; + } + if (VE(vid1, 0) == -1) { + VE(vid1, 0) = i; + } else if (VE(vid1, 1) == -1) { + VE(vid1, 1) = i; + } + } + + // compute EE + for (size_t i = 0; i < VE.rows(); i++) { + long eid0 = VE(i, 0); + long eid1 = VE(i, 1); + if (EE(eid0, 0) == -1) { + EE(eid0, 0) = eid1; + } else if (EE(eid1, 0) == -1) { + EE(eid0, 1) = eid1; + } + if (EE(eid0, 0) == -1) { + EE(eid1, 0) = eid0; + } else if (EE(eid1, 0) == -1) { + EE(eid1, 1) = eid0; + } + } + + initialize(E, EE, VE); +} + void EdgeMesh::initialize( Eigen::Ref EV, Eigen::Ref EE, - Eigen::Ref VE) + Eigen::Ref VE) { throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); std::vector cap{ @@ -119,12 +174,11 @@ void EdgeMesh::initialize( // m_vf for (long i = 0; i < capacity(PrimitiveType::Vertex); ++i) { - ve_accessor.index_access().scalar_attribute(i) = VE(i); - e_flag_accessor.index_access().scalar_attribute(i) |= 0x1; + ve_accessor.index_access().vector_attribute(i) = VE.row(i).transpose(); + // e_flag_accessor.index_access().scalar_attribute(i) |= 0x1; } } - bool EdgeMesh::is_valid(const Tuple& tuple, ConstAccessor& hash_accessor) const { throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); @@ -163,7 +217,7 @@ Tuple EdgeMesh::vertex_tuple_from_id(long id) const auto ev = ev_accessor.index_access().vector_attribute(e); for (long i = 0; i < 2; ++i) { if (ev(i) == id) { - assert(autogen::auto_2d_table_complete_vertex[i][0] == i); + // assert(autogen::auto_2d_table_complete_vertex[i][0] == i); // do not know if I use this function right. Tuple v_tuple = Tuple( i, diff --git a/src/wmtk/EdgeMesh.hpp b/src/wmtk/EdgeMesh.hpp index 201e267962..580f4129de 100644 --- a/src/wmtk/EdgeMesh.hpp +++ b/src/wmtk/EdgeMesh.hpp @@ -17,10 +17,12 @@ class EdgeMesh : public Mesh EdgeMesh& operator=(const EdgeMesh& o); EdgeMesh& operator=(EdgeMesh&& o); + void initialize(Eigen::Ref E); + void initialize( Eigen::Ref EV, Eigen::Ref EE, - Eigen::Ref VE); + Eigen::Ref VE); PrimitiveType top_simplex_type() const override { return PrimitiveType::Edge; } Tuple switch_tuple(const Tuple& tuple, PrimitiveType type) const override; diff --git a/src/wmtk/EdgeMeshOperationExecutor.cpp b/src/wmtk/EdgeMeshOperationExecutor.cpp index 673304c562..a88d2d84f0 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.cpp +++ b/src/wmtk/EdgeMeshOperationExecutor.cpp @@ -92,156 +92,17 @@ EdgeMesh::EdgeMeshOperationExecutor::get_collapse_simplices_to_delete( std::vector> EdgeMesh::EdgeMeshOperationExecutor::prepare_operating_tuples_for_child_meshes() const { - std::vector> vec_t_child(m_incident_face_datas.size()); - for (long i = 0; i < long(m_incident_face_datas.size()); ++i) { - vec_t_child[i] = MultiMeshManager::map_edge_tuple_to_all_children( - m_mesh, - m_incident_face_datas[i].local_operating_tuple); - } - // clean up redundant - if (m_incident_face_datas.size() > 1) { - for (long j = 0; j < long(vec_t_child[1].size()); ++j) { - auto child_mesh_ptr = m_mesh.multi_mesh_manager.child_meshes[j]; - if (vec_t_child[1][j].is_null() || vec_t_child[0][j].is_null()) { - continue; - } - if (child_mesh_ptr->simplices_are_equal( - Simplex::edge(vec_t_child[0][j]), - Simplex::edge(vec_t_child[1][j]))) { - vec_t_child[1][j] = Tuple(); // redundant, set as null tuple - } - } - } - return vec_t_child; + return std::vector>(); } Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge() { - if (!m_mesh.multi_mesh_manager.is_parent_mesh()) { - return split_edge_single_mesh(); - } else { - std::vector> vec_t_child = prepare_operating_tuples_for_child_meshes(); - - // do split on parent_mesh - Tuple ret_tuple = split_edge_single_mesh(); - - for (auto child_mesh_ptr : m_mesh.multi_mesh_manager.child_meshes) { - long child_id = child_mesh_ptr->multi_mesh_manager.child_id(); - if (child_mesh_ptr->top_simplex_type() == PrimitiveType::Face) { - // this child_mesh is a EdgeMesh - EdgeMesh& child_tri_mesh = *std::static_pointer_cast(child_mesh_ptr); - - std::vector> child_new_cell_ids; - for (long i = 0; i < long(m_incident_face_datas.size()); ++i) { - Tuple t_child = vec_t_child[i][child_id]; - if (t_child.is_null()) { - if (child_new_cell_ids.size() <= i) child_new_cell_ids.emplace_back(-1, -1); - continue; - } - auto child_hash_acc = child_tri_mesh.get_cell_hash_accessor(); - EdgeMesh::EdgeMeshOperationExecutor executor_child( - child_tri_mesh, - t_child, - child_hash_acc); - executor_child.split_edge(); - for (auto child_incident_face_data : executor_child.m_incident_face_datas) { - child_new_cell_ids.emplace_back( - child_incident_face_data.split_f0, - child_incident_face_data.split_f1); - } - } - - assert(child_new_cell_ids.size() == m_incident_face_datas.size()); - - // update_hash on new cells - for (long i = 0; i < long(m_incident_face_datas.size()); i++) { - const auto& split_fs_child = child_new_cell_ids[i]; - long split_f0_child = split_fs_child.first; - long split_f1_child = split_fs_child.second; - - const auto& incident_face_data = m_incident_face_datas[i]; - long split_f0_parent = incident_face_data.split_f0; - long split_f1_parent = incident_face_data.split_f1; - - Tuple tuple_child = (split_f0_child == -1) - ? Tuple() - : child_tri_mesh.face_tuple_from_id(split_f0_child); - Tuple tuple_parent = m_mesh.face_tuple_from_id(split_f0_parent); - - if (!tuple_child.is_null()) { - MultiMeshManager::write_tuple_map_attribute( - child_tri_mesh.multi_mesh_manager.map_to_parent_handle, - child_tri_mesh, - tuple_child, - tuple_parent); - } - MultiMeshManager::write_tuple_map_attribute( - m_mesh.multi_mesh_manager.map_to_child_handles[child_id], - m_mesh, - tuple_parent, - tuple_child); - - tuple_child = (split_f1_child == -1) - ? Tuple() - : child_tri_mesh.face_tuple_from_id(split_f1_child); - tuple_parent = m_mesh.face_tuple_from_id(split_f1_parent); - if (!tuple_child.is_null()) { - MultiMeshManager::write_tuple_map_attribute( - child_tri_mesh.multi_mesh_manager.map_to_parent_handle, - child_tri_mesh, - tuple_child, - tuple_parent); - } - MultiMeshManager::write_tuple_map_attribute( - m_mesh.multi_mesh_manager.map_to_child_handles[child_id], - m_mesh, - tuple_parent, - tuple_child); - } - - // update_hash on neighboring cells - update_hash_in_map(child_tri_mesh); - } - } - return ret_tuple; - } + return Tuple(); } Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge_single_mesh() { - simplex_ids_to_delete = get_split_simplices_to_delete(m_operating_tuple, m_mesh); - - // create new vertex (center) - std::vector new_vids = this->request_simplex_indices(PrimitiveType::Vertex, 1); - assert(new_vids.size() == 1); - const long v_new = new_vids[0]; - - // create new edges (spine) - std::vector new_eids = this->request_simplex_indices(PrimitiveType::Edge, 2); - assert(new_eids.size() == 2); - - for (IncidentFaceData& face_data : m_incident_face_datas) { - replace_incident_face(v_new, new_eids, face_data); - } - assert(m_incident_face_datas.size() <= 2); - if (m_incident_face_datas.size() > 1) { - connect_faces_across_spine(); - } - - update_cell_hash(); - delete_simplices(); - // return Tuple new_fid, new_vid that points - const long new_tuple_fid = m_incident_face_datas[0].split_f1; - Tuple ret = m_mesh.edge_tuple_from_id(new_eids[1]); - if (m_mesh.id_vertex(ret) != v_new) { - ret = m_mesh.switch_vertex(ret); - } - if (m_mesh.id_face(ret) != new_tuple_fid) { - ret = m_mesh.switch_face(ret); - } - assert(m_mesh.is_valid_slow(ret)); - - return ret; + return Tuple(); // return m_mesh.with_different_cid(m_operating_tuple, m_incident_face_datas[0].split_f0); } @@ -286,92 +147,13 @@ void EdgeMesh::EdgeMeshOperationExecutor::update_hash_in_map(EdgeMesh& child_mes Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge() { - if (!m_mesh.multi_mesh_manager.is_parent_mesh()) { - return collapse_edge_single_mesh(); - } else { - std::vector> vec_t_child = prepare_operating_tuples_for_child_meshes(); - - // do collapse on parent_mesh - Tuple ret_tuple = collapse_edge_single_mesh(); - - for (auto child_mesh_ptr : m_mesh.multi_mesh_manager.child_meshes) { - long child_id = child_mesh_ptr->multi_mesh_manager.child_id(); - - if (child_mesh_ptr->top_simplex_type() == PrimitiveType::Face) { - // this child_mesh is a EdgeMesh - EdgeMesh& child_tri_mesh = *std::static_pointer_cast(child_mesh_ptr); - - for (long i = 0; i < long(m_incident_face_datas.size()); ++i) { - Tuple t_child = vec_t_child[i][child_id]; - if (t_child.is_null()) { - continue; - } - auto child_hash_acc = child_tri_mesh.get_cell_hash_accessor(); - EdgeMesh::EdgeMeshOperationExecutor executor_child( - child_tri_mesh, - t_child, - child_hash_acc); - executor_child.collapse_edge(); - } - // update_hash - update_hash_in_map(child_tri_mesh); - } - } - - return ret_tuple; - } + return Tuple(); } Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge_single_mesh() { - simplex_ids_to_delete = get_collapse_simplices_to_delete(m_operating_tuple, m_mesh); - - // must collect star before changing connectivity - const SimplicialComplex v0_star = - SimplicialComplex::closed_star(m_mesh, Simplex::vertex(m_operating_tuple)); - - - connect_ears(); - - const long& v0 = m_spine_vids[0]; - const long& v1 = m_spine_vids[1]; - - // replace v0 by v1 in incident faces - for (const Simplex& f : v0_star.get_faces()) { - const long fid = m_mesh.id(f); - auto fv = fv_accessor.index_access().vector_attribute(fid); - for (long i = 0; i < 3; ++i) { - if (fv[i] == v0) { - fv[i] = v1; - break; - } - } - } - - const long& ret_eid = m_incident_face_datas[0].ears[1].eid; - const long& ret_vid = m_spine_vids[1]; - const long& ef0 = m_incident_face_datas[0].ears[0].fid; - const long& ef1 = m_incident_face_datas[0].ears[1].fid; - - const long new_tuple_fid = (ef0 > -1) ? ef0 : ef1; - - update_cell_hash(); - delete_simplices(); - - Tuple ret = m_mesh.edge_tuple_from_id(ret_eid); - if (m_mesh.id_vertex(ret) != ret_vid) { - ret = m_mesh.switch_vertex(ret); - } - assert(m_mesh.id_vertex(ret) == ret_vid); - if (m_mesh.id_face(ret) != new_tuple_fid) { - ret = m_mesh.switch_face(ret); - } - assert(m_mesh.id_face(ret) == new_tuple_fid); - assert(m_mesh.is_valid_slow(ret)); - - - return ret; + return Tuple(); // return a ccw tuple from left ear if it exists, otherwise return a ccw tuple from right ear // return m_mesh.tuple_from_id(PrimitiveType::Vertex, v1); @@ -381,9 +163,7 @@ std::vector EdgeMesh::EdgeMeshOperationExecutor::request_simplex_indices( const PrimitiveType type, long count) { - m_mesh.reserve_attributes(type, m_mesh.capacity(type) + count); - - return m_mesh.request_simplex_indices(type, count); + return std::vector(); } } // namespace wmtk diff --git a/src/wmtk/EdgeMeshOperationExecutor.hpp b/src/wmtk/EdgeMeshOperationExecutor.hpp index 1e4656f7a4..0a34e1b495 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.hpp +++ b/src/wmtk/EdgeMeshOperationExecutor.hpp @@ -11,7 +11,7 @@ class EdgeMesh::EdgeMeshOperationExecutor void delete_simplices(); void update_cell_hash(); - std::array, 3> flag_accessors; + std::array, 2> flag_accessors; Accessor ee_accessor; Accessor ev_accessor; Accessor ve_accessor; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ca1438a3a8..f5102c7272 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -17,6 +17,7 @@ set(TEST_SOURCES test_execution.cpp test_simplex_collection.cpp test_simplicial_complex.cpp + test_1d_operations.cpp test_2d_operations.cpp test_2d_operation_construction.cpp test_accessor.cpp @@ -28,6 +29,8 @@ set(TEST_SOURCES tools/DEBUG_EdgeMesh.cpp tools/DEBUG_TriMesh.hpp tools/DEBUG_TriMesh.cpp + tools/EdgeMesh_examples.hpp + tools/EdgeMesh_examples.cpp tools/TriMesh_examples.hpp tools/TriMesh_examples.cpp tools/redirect_logger_to_cout.hpp diff --git a/tests/test_1d_operations.cpp b/tests/test_1d_operations.cpp new file mode 100644 index 0000000000..15cd467320 --- /dev/null +++ b/tests/test_1d_operations.cpp @@ -0,0 +1,29 @@ +#include + +#include +#include +#include +#include +#include +#include "tools/DEBUG_EdgeMesh.hpp" +#include "tools/EdgeMesh_examples.hpp" + +using namespace wmtk; +using namespace wmtk::tests; + +using EM = EdgeMesh; +using MapResult = typename Eigen::Matrix::MapType; +using TMOE = decltype(std::declval().get_tmoe( + wmtk::Tuple(), + std::declval&>())); + +constexpr PrimitiveType PV = PrimitiveType::Vertex; +constexpr PrimitiveType PE = PrimitiveType::Edge; + +TEST_CASE("1D_initialize", "[operations][1D]") +{ + // DEBUG_EdgeMesh; + DEBUG_EdgeMesh mesh0 = simple_line(); + DEBUG_EdgeMesh mesh1 = loop_line(); + DEBUG_EdgeMesh mesh2 = multiple_lines(); +} \ No newline at end of file diff --git a/tests/test_2d_operation_construction.cpp b/tests/test_2d_operation_construction.cpp index f31e6171fc..1fbae22455 100644 --- a/tests/test_2d_operation_construction.cpp +++ b/tests/test_2d_operation_construction.cpp @@ -51,7 +51,6 @@ DEBUG_TriMesh test_split(const DEBUG_TriMesh& mesh, long edge_index, bool should return test_split(mesh, e, should_succeed); } - // because TriMesh::collapse_edge isn'ta waare of preconditions we need to tell the system whether // something should succeed DEBUG_TriMesh test_collapse(const DEBUG_TriMesh& mesh, const Tuple& e, bool should_succeed) diff --git a/tests/tools/EdgeMesh_examples.cpp b/tests/tools/EdgeMesh_examples.cpp new file mode 100644 index 0000000000..f62f42c53b --- /dev/null +++ b/tests/tools/EdgeMesh_examples.cpp @@ -0,0 +1,45 @@ +#include "EdgeMesh_examples.hpp" + + +namespace wmtk::tests { +EdgeMesh simple_line() +{ + EdgeMesh m; + RowVectors2l edges; + edges.resize(4, 2); + edges.row(0) << 0, 1; + edges.row(1) << 1, 2; + edges.row(2) << 2, 3; + edges.row(3) << 3, 4; + m.initialize(edges); + return m; +} +EdgeMesh loop_line() +{ + EdgeMesh m; + RowVectors2l edges; + edges.resize(4, 2); + edges.row(0) << 0, 1; + edges.row(1) << 1, 2; + edges.row(2) << 2, 3; + edges.row(3) << 3, 0; + m.initialize(edges); + return m; +} +EdgeMesh multiple_lines() +{ + EdgeMesh m; + RowVectors2l edges; + edges.resize(8, 2); + edges.row(0) << 0, 1; + edges.row(1) << 1, 2; + edges.row(2) << 2, 3; + edges.row(3) << 3, 4; + edges.row(4) << 5, 6; + edges.row(5) << 6, 7; + edges.row(6) << 7, 8; + edges.row(7) << 8, 9; + m.initialize(edges); + return m; +} +} // namespace wmtk::tests \ No newline at end of file diff --git a/tests/tools/EdgeMesh_examples.hpp b/tests/tools/EdgeMesh_examples.hpp new file mode 100644 index 0000000000..eb71c91ce5 --- /dev/null +++ b/tests/tools/EdgeMesh_examples.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace wmtk::tests { +EdgeMesh simple_line(); +EdgeMesh loop_line(); +EdgeMesh multiple_lines(); +} // namespace wmtk::tests \ No newline at end of file From 01ba6f130f3dd2c8e001bb0f837e468475f944e4 Mon Sep 17 00:00:00 2001 From: zhouyuan chen <867442167@qq.com> Date: Tue, 26 Sep 2023 21:02:43 -0400 Subject: [PATCH 07/49] fix a bug for EdgeMesh::initialize, the loop's condition wrong. --- src/wmtk/EdgeMesh.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/wmtk/EdgeMesh.cpp b/src/wmtk/EdgeMesh.cpp index 1d3ded9f05..22e65addbf 100644 --- a/src/wmtk/EdgeMesh.cpp +++ b/src/wmtk/EdgeMesh.cpp @@ -126,15 +126,17 @@ void EdgeMesh::initialize(Eigen::Ref E) for (size_t i = 0; i < VE.rows(); i++) { long eid0 = VE(i, 0); long eid1 = VE(i, 1); - if (EE(eid0, 0) == -1) { - EE(eid0, 0) = eid1; - } else if (EE(eid1, 0) == -1) { - EE(eid0, 1) = eid1; - } - if (EE(eid0, 0) == -1) { - EE(eid1, 0) = eid0; - } else if (EE(eid1, 0) == -1) { - EE(eid1, 1) = eid0; + if (eid0 != -1 && eid1 != -1) { + if (EE(eid0, 0) == -1) { + EE(eid0, 0) = eid1; + } else if (EE(eid1, 0) == -1) { + EE(eid0, 1) = eid1; + } + if (EE(eid1, 0) == -1) { + EE(eid1, 0) = eid0; + } else if (EE(eid1, 0) == -1) { + EE(eid1, 1) = eid0; + } } } From 37392a776765fcdfd255f96a3fca60e2f6d8d5f9 Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Wed, 27 Sep 2023 14:22:44 -0400 Subject: [PATCH 08/49] get the desired frame for edgemesh operation executor --- src/wmtk/EdgeMeshOperationExecutor.cpp | 105 ++++++------------------- src/wmtk/EdgeMeshOperationExecutor.hpp | 6 +- 2 files changed, 28 insertions(+), 83 deletions(-) diff --git a/src/wmtk/EdgeMeshOperationExecutor.cpp b/src/wmtk/EdgeMeshOperationExecutor.cpp index a88d2d84f0..c674862882 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.cpp +++ b/src/wmtk/EdgeMeshOperationExecutor.cpp @@ -16,27 +16,20 @@ EdgeMesh::EdgeMeshOperationExecutor::EdgeMeshOperationExecutor( , m_operating_tuple(operating_tuple) { - // store ids of edge and incident vertices + Tuple operating_tuple_switch_vertex = m_mesh.switch_vertex(operating_tuple); + // store ids of incident vertices m_operating_edge_id = m_mesh.id_edge(m_operating_tuple); m_spine_vids[0] = m_mesh.id_vertex(m_operating_tuple); - m_spine_vids[1] = m_mesh.id_vertex(m_mesh.switch_vertex(m_operating_tuple)); + m_spine_vids[1] = m_mesh.id_vertex(operating_tuple_switch_vertex); - const SimplicialComplex edge_closed_star = - SimplicialComplex::closed_star(m_mesh, Simplex::edge(operating_tuple)); - - // get all faces incident to the edge - for (const Simplex& f : edge_closed_star.get_faces()) { - // m_incident_face_datas.emplace_back(get_incident_face_data(f.tuple())); - } - - // update hash on all faces in the two-ring neighborhood - SimplicialComplex hash_update_region(m); - for (const Simplex& v : edge_closed_star.get_vertices()) { - const SimplicialComplex v_closed_star = SimplicialComplex::closed_star(m_mesh, v); - hash_update_region.unify_with_complex(v_closed_star); + // update hash on neighborhood + cell_ids_to_update_hash.emplace_back(m_mesh.id_edge(m_operating_tuple)); + if (m_mesh.is_boundary(m_operating_tuple)) { + cell_ids_to_update_hash.emplace_back(m_mesh.id_edge(m_mesh.switch_edge(m_operating_tuple))); } - for (const Simplex& f : hash_update_region.get_faces()) { - cell_ids_to_update_hash.push_back(m_mesh.id(f)); + if (m_mesh.is_boundary(operating_tuple_switch_vertex)) { + cell_ids_to_update_hash.emplace_back( + m_mesh.id_edge(m_mesh.switch_edge(operating_tuple_switch_vertex))); } } @@ -54,38 +47,23 @@ void EdgeMesh::EdgeMeshOperationExecutor::update_cell_hash() m_mesh.update_cell_hashes(cell_ids_to_update_hash, hash_accessor); } -const std::array, 3> +const std::array, 2> EdgeMesh::EdgeMeshOperationExecutor::get_split_simplices_to_delete( const Tuple& tuple, const EdgeMesh& m) { - const SimplicialComplex sc = SimplicialComplex::open_star(m, Simplex::edge(tuple)); - std::array, 3> ids; - for (const Simplex& s : sc.get_simplices()) { - ids[get_simplex_dimension(s.primitive_type())].emplace_back(m.id(s)); - } - + // TODO: Implement this + std::array, 2> ids; return ids; } -const std::array, 3> +const std::array, 2> EdgeMesh::EdgeMeshOperationExecutor::get_collapse_simplices_to_delete( const Tuple& tuple, const EdgeMesh& m) { - const SimplicialComplex vertex_open_star = - SimplicialComplex::open_star(m, Simplex::vertex(tuple)); - const SimplicialComplex edge_closed_star = - SimplicialComplex::closed_star(m, Simplex::edge(tuple)); - - const SimplicialComplex sc = - SimplicialComplex::get_intersection(vertex_open_star, edge_closed_star); - - std::array, 3> ids; - for (const Simplex& s : sc.get_simplices()) { - ids[get_simplex_dimension(s.primitive_type())].emplace_back(m.id(s)); - } - + // TODO: Implement this + std::array, 2> ids; return ids; } @@ -97,73 +75,40 @@ EdgeMesh::EdgeMeshOperationExecutor::prepare_operating_tuples_for_child_meshes() Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge() { - return Tuple(); + return split_edge_single_mesh(); + // TODO: Implement for multi_mesh in the future } Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge_single_mesh() { + // TODO: Implement this return Tuple(); - // return m_mesh.with_different_cid(m_operating_tuple, m_incident_face_datas[0].split_f0); } void EdgeMesh::EdgeMeshOperationExecutor::update_hash_in_map(EdgeMesh& child_mesh) { - long child_id = child_mesh.multi_mesh_manager.child_id(); - auto child_hash_accessor = child_mesh.get_cell_hash_accessor(); - - for (auto parent_cell_id : cell_ids_to_update_hash) { - auto [t_parent_old, t_child_old] = MultiMeshManager::read_tuple_map_attribute( - m_mesh.multi_mesh_manager.map_to_child_handles[child_id], - m_mesh, - m_mesh.tuple_from_id(m_mesh.top_simplex_type(), parent_cell_id)); - - long parent_cell_hash = m_mesh.get_cell_hash_slow(parent_cell_id); - Tuple t_parent_new = t_parent_old.with_updated_hash(parent_cell_hash); - - if (t_child_old.is_null()) { - MultiMeshManager::write_tuple_map_attribute( - m_mesh.multi_mesh_manager.map_to_child_handles[child_id], - m_mesh, - t_parent_new, - Tuple()); - } else { - long child_cell_hash = - child_hash_accessor.index_access().const_scalar_attribute(t_child_old.m_global_cid); - Tuple t_child_new = t_child_old.with_updated_hash(child_cell_hash); - MultiMeshManager::write_tuple_map_attribute( - m_mesh.multi_mesh_manager.map_to_child_handles[child_id], - m_mesh, - t_parent_new, - t_child_new); - - MultiMeshManager::write_tuple_map_attribute( - child_mesh.multi_mesh_manager.map_to_parent_handle, - child_mesh, - t_child_new, - t_parent_new); - } - } + // TODO: Implement for multi_mesh in the future } Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge() { - return Tuple(); + return collapse_edge_single_mesh(); + // TODO: Implement for multi_mesh in the future } Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge_single_mesh() { + // TODO: Implement this return Tuple(); - - // return a ccw tuple from left ear if it exists, otherwise return a ccw tuple from right ear - // return m_mesh.tuple_from_id(PrimitiveType::Vertex, v1); } std::vector EdgeMesh::EdgeMeshOperationExecutor::request_simplex_indices( const PrimitiveType type, long count) { - return std::vector(); + m_mesh.reserve_attributes(type, m_mesh.capacity(type) + count); + return m_mesh.request_simplex_indices(type, count); } } // namespace wmtk diff --git a/src/wmtk/EdgeMeshOperationExecutor.hpp b/src/wmtk/EdgeMeshOperationExecutor.hpp index 0a34e1b495..f45979f247 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.hpp +++ b/src/wmtk/EdgeMeshOperationExecutor.hpp @@ -22,7 +22,7 @@ class EdgeMesh::EdgeMeshOperationExecutor * * The deleted simplices are exactly the open star of the edge */ - static const std::array, 3> get_split_simplices_to_delete( + static const std::array, 2> get_split_simplices_to_delete( const Tuple& tuple, const EdgeMesh& m); @@ -33,7 +33,7 @@ class EdgeMesh::EdgeMeshOperationExecutor * of the edge. This comes down to one vertex, three edges, and two faces if the edge is on the * interior. On the boundary it is one vertex, two edges, and one face. */ - static const std::array, 3> get_collapse_simplices_to_delete( + static const std::array, 2> get_collapse_simplices_to_delete( const Tuple& tuple, const EdgeMesh& m); @@ -48,7 +48,7 @@ class EdgeMesh::EdgeMeshOperationExecutor std::vector request_simplex_indices(const PrimitiveType type, long count); - std::array, 3> simplex_ids_to_delete; + std::array, 2> simplex_ids_to_delete; std::vector cell_ids_to_update_hash; EdgeMesh& m_mesh; Tuple m_operating_tuple; From b551d2d88d360999040438c0854bb9af5336af78 Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Wed, 27 Sep 2023 15:43:01 -0400 Subject: [PATCH 09/49] implement edgemesh split_edge --- src/wmtk/EdgeMeshOperationExecutor.cpp | 64 ++++++++++++++++++++++---- src/wmtk/EdgeMeshOperationExecutor.hpp | 3 +- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/src/wmtk/EdgeMeshOperationExecutor.cpp b/src/wmtk/EdgeMeshOperationExecutor.cpp index c674862882..8c659577d0 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.cpp +++ b/src/wmtk/EdgeMeshOperationExecutor.cpp @@ -25,11 +25,12 @@ EdgeMesh::EdgeMeshOperationExecutor::EdgeMeshOperationExecutor( // update hash on neighborhood cell_ids_to_update_hash.emplace_back(m_mesh.id_edge(m_operating_tuple)); if (m_mesh.is_boundary(m_operating_tuple)) { - cell_ids_to_update_hash.emplace_back(m_mesh.id_edge(m_mesh.switch_edge(m_operating_tuple))); + m_neighbor_eids[0] = m_mesh.id_edge(m_mesh.switch_edge(m_operating_tuple)); + cell_ids_to_update_hash.emplace_back(m_neighbor_eids[0]); } if (m_mesh.is_boundary(operating_tuple_switch_vertex)) { - cell_ids_to_update_hash.emplace_back( - m_mesh.id_edge(m_mesh.switch_edge(operating_tuple_switch_vertex))); + m_neighbor_eids[1] = m_mesh.id_edge(m_mesh.switch_edge(operating_tuple_switch_vertex)); + cell_ids_to_update_hash.emplace_back(m_neighbor_eids[1]); } } @@ -52,8 +53,8 @@ EdgeMesh::EdgeMeshOperationExecutor::get_split_simplices_to_delete( const Tuple& tuple, const EdgeMesh& m) { - // TODO: Implement this std::array, 2> ids; + ids[1].emplace_back(m.id_edge(tuple)); return ids; } @@ -62,15 +63,17 @@ EdgeMesh::EdgeMeshOperationExecutor::get_collapse_simplices_to_delete( const Tuple& tuple, const EdgeMesh& m) { - // TODO: Implement this std::array, 2> ids; + ids[0].emplace_back(m.id_vertex(tuple)); + ids[1].emplace_back(m.id_edge(tuple)); return ids; } -std::vector> -EdgeMesh::EdgeMeshOperationExecutor::prepare_operating_tuples_for_child_meshes() const +std::vector EdgeMesh::EdgeMeshOperationExecutor::prepare_operating_tuples_for_child_meshes() + const { - return std::vector>(); + // this function is designed as a helper for multi_mesh + return MultiMeshManager::map_edge_tuple_to_all_children(m_mesh, m_operating_tuple); } Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge() @@ -81,7 +84,46 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge() Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge_single_mesh() { - // TODO: Implement this + simplex_ids_to_delete = get_split_simplices_to_delete(m_operating_tuple, m_mesh); + + // create new vertex (center) + std::vector new_vids = this->request_simplex_indices(PrimitiveType::Vertex, 1); + assert(new_vids.size() == 1); + const long v_new = new_vids[0]; + // create new edges + std::vector new_eids = this->request_simplex_indices(PrimitiveType::Edge, 2); + assert(new_eids.size() == 2); + + long local_vid = m_mesh.is_ccw(m_operating_tuple) ? 0 : 1; + + // update ee + { + auto ee_new_0 = ee_accessor.index_access().vector_attribute(new_eids[0]); + auto ee_new_1 = ee_accessor.index_access().vector_attribute(new_eids[1]); + ee_new_0[local_vid] = m_neighbor_eids[0]; + ee_new_0[(local_vid + 1) % 2] = new_eids[1]; + ee_new_1[local_vid] = new_eids[0]; + ee_new_1[(local_vid + 1) % 2] = m_neighbor_eids[1]; + for (long i = 0; i < 2; i++) { + if (m_neighbor_eids[i] != -1) { + ee_accessor.index_access().vector_attribute( + m_neighbor_eids[i])[(local_vid + 1) % 2] = new_eids[i]; + } + } + } + // update ev + { + ev_accessor.index_access().scalar_attribute(new_eids[0]) = v_new; + ev_accessor.index_access().scalar_attribute(new_eids[1]) = v_new; + } + // update ve + { + ve_accessor.index_access().scalar_attribute(v_new) = new_eids[0]; + ve_accessor.index_access().scalar_attribute(m_spine_vids[0]) = new_eids[0]; + ve_accessor.index_access().scalar_attribute(m_spine_vids[1]) = new_eids[1]; + } + update_cell_hash(); + delete_simplices(); return Tuple(); } @@ -99,7 +141,11 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge() Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge_single_mesh() { + simplex_ids_to_delete = get_collapse_simplices_to_delete(m_operating_tuple, m_mesh); // TODO: Implement this + + update_cell_hash(); + delete_simplices(); return Tuple(); } diff --git a/src/wmtk/EdgeMeshOperationExecutor.hpp b/src/wmtk/EdgeMeshOperationExecutor.hpp index f45979f247..eb0f83f506 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.hpp +++ b/src/wmtk/EdgeMeshOperationExecutor.hpp @@ -55,11 +55,12 @@ class EdgeMesh::EdgeMeshOperationExecutor private: - std::vector> prepare_operating_tuples_for_child_meshes() const; + std::vector prepare_operating_tuples_for_child_meshes() const; void update_hash_in_map(EdgeMesh& child_mesh); // common simplicies std::array m_spine_vids; // V_A_id, V_B_id; + std::array m_neighbor_eids = {-1, -1}; long m_operating_edge_id; }; } // namespace wmtk From 913e166ccaf0ef3c475d98fe5abd1e747ba3f415 Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Wed, 27 Sep 2023 15:49:32 -0400 Subject: [PATCH 10/49] fimish edgemesh split_edge with return tuple --- src/wmtk/EdgeMeshOperationExecutor.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/wmtk/EdgeMeshOperationExecutor.cpp b/src/wmtk/EdgeMeshOperationExecutor.cpp index 8c659577d0..40a1845314 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.cpp +++ b/src/wmtk/EdgeMeshOperationExecutor.cpp @@ -86,11 +86,12 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge_single_mesh() { simplex_ids_to_delete = get_split_simplices_to_delete(m_operating_tuple, m_mesh); - // create new vertex (center) + // create new vertex std::vector new_vids = this->request_simplex_indices(PrimitiveType::Vertex, 1); assert(new_vids.size() == 1); const long v_new = new_vids[0]; // create new edges + // new_eids[i] is connect to m_neighbor_eids[i] and m_spine_vids[i] std::vector new_eids = this->request_simplex_indices(PrimitiveType::Edge, 2); assert(new_eids.size() == 2); @@ -124,7 +125,9 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge_single_mesh() } update_cell_hash(); delete_simplices(); - return Tuple(); + + // prepare return Tuple + return m_mesh.edge_tuple_from_id(new_eids[0]); } void EdgeMesh::EdgeMeshOperationExecutor::update_hash_in_map(EdgeMesh& child_mesh) @@ -141,6 +144,12 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge() Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge_single_mesh() { + // check if the collapse is valid + if (m_mesh.is_boundary(m_operating_tuple) && + m_mesh.is_boundary(m_mesh.switch_vertex(m_operating_tuple))) { + return Tuple(); + } + simplex_ids_to_delete = get_collapse_simplices_to_delete(m_operating_tuple, m_mesh); // TODO: Implement this From 455c8676d01ef60565a9765e4b0d1cf411b973f9 Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Wed, 27 Sep 2023 16:05:01 -0400 Subject: [PATCH 11/49] correct edgemsh split without aorientation assumptions --- src/wmtk/EdgeMeshOperationExecutor.cpp | 41 ++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/src/wmtk/EdgeMeshOperationExecutor.cpp b/src/wmtk/EdgeMeshOperationExecutor.cpp index 40a1845314..7cf5593f3b 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.cpp +++ b/src/wmtk/EdgeMeshOperationExecutor.cpp @@ -107,15 +107,23 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge_single_mesh() ee_new_1[(local_vid + 1) % 2] = m_neighbor_eids[1]; for (long i = 0; i < 2; i++) { if (m_neighbor_eids[i] != -1) { - ee_accessor.index_access().vector_attribute( - m_neighbor_eids[i])[(local_vid + 1) % 2] = new_eids[i]; + auto ee_neighbor = ee_accessor.index_access().vector_attribute(m_neighbor_eids[i]); + for (long j = 0; j < 2; j++) { + if (ee_neighbor[j] == m_operating_edge_id) { + ee_neighbor[j] = new_eids[i]; + } + } } } } // update ev { - ev_accessor.index_access().scalar_attribute(new_eids[0]) = v_new; - ev_accessor.index_access().scalar_attribute(new_eids[1]) = v_new; + auto ev_new_0 = ev_accessor.index_access().vector_attribute(new_eids[0]); + auto ev_new_1 = ev_accessor.index_access().vector_attribute(new_eids[1]); + ev_new_0[local_vid] = m_spine_vids[0]; + ev_new_0[(local_vid + 1) % 2] = v_new; + ev_new_1[local_vid] = v_new; + ev_new_1[(local_vid + 1) % 2] = m_spine_vids[1]; } // update ve { @@ -151,7 +159,30 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge_single_mesh() } simplex_ids_to_delete = get_collapse_simplices_to_delete(m_operating_tuple, m_mesh); - // TODO: Implement this + + // update ee + { + for (long i = 0; i < 2; i++) { + if (m_neighbor_eids[i] != -1) { + auto ee_neighbor = ee_accessor.index_access().vector_attribute(m_neighbor_eids[i]); + for (long j = 0; j < 2; j++) { + if (ee_neighbor[j] == m_operating_edge_id) { + ee_neighbor[j] = m_neighbor_eids[(i + 1) % 2]; + } + } + } + } + } + + // update ev + { + // TODO: implement this + } + + // update ve + { + // TODO: implement this + } update_cell_hash(); delete_simplices(); From a75edd43509c5f00a906381d4f9e09b85cec58a0 Mon Sep 17 00:00:00 2001 From: JcDai Date: Wed, 27 Sep 2023 16:27:38 -0400 Subject: [PATCH 12/49] implement edge mesh connectivity --- src/wmtk/EdgeMesh.cpp | 536 +++++++++++++----- src/wmtk/EdgeMesh.hpp | 55 +- src/wmtk/TriMesh.cpp | 4 +- src/wmtk/utils/CMakeLists.txt | 2 + .../edgemesh_topology_initialization.cpp | 52 ++ .../utils/edgemesh_topology_initialization.h | 12 + 6 files changed, 484 insertions(+), 177 deletions(-) create mode 100644 src/wmtk/utils/edgemesh_topology_initialization.cpp create mode 100644 src/wmtk/utils/edgemesh_topology_initialization.h diff --git a/src/wmtk/EdgeMesh.cpp b/src/wmtk/EdgeMesh.cpp index 22e65addbf..2cd95d6e2d 100644 --- a/src/wmtk/EdgeMesh.cpp +++ b/src/wmtk/EdgeMesh.cpp @@ -6,229 +6,183 @@ EdgeMesh::EdgeMesh() , m_ev_handle(register_attribute("m_ev", PrimitiveType::Edge, 2)) , m_ee_handle(register_attribute("m_ee", PrimitiveType::Edge, 2)) {} -// EdgeMesh::EdgeMesh(const EdgeMesh&& o) = default; +EdgeMesh::EdgeMesh(const EdgeMesh& o) = default; EdgeMesh::EdgeMesh(EdgeMesh&& o) = default; EdgeMesh& EdgeMesh::operator=(const EdgeMesh& o) = default; EdgeMesh& EdgeMesh::operator=(EdgeMesh&& o) = default; -Tuple EdgeMesh::tuple_from_id(const PrimitiveType type, const long gid) const +Tuple EdgeMesh::split_edge(const Tuple& t, Accessor& hash_accessor) +{ + // TODO: to be implemented after operations + return Tuple(); +} + +Tuple EdgeMesh::collapse_edge(const Tuple& t, Accessor& hash_accessor) +{ + // TODO: to be implemented after operations + return Tuple(); +} + +long EdgeMesh::id(const Tuple& tuple, PrimitiveType) const { - throw std::runtime_error("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); switch (type) { case PrimitiveType::Vertex: { - return vertex_tuple_from_id(gid); + ConstAccessor ev_accessor = create_const_accessor(m_ev_handle); + auto ev = ev_accessor.vertex_attribute(tuple); + return fv(tuple.m_local_vid); } case PrimitiveType::Edge: { - return edge_tuple_from_id(gid); - } - case PrimitiveType::Face: { - throw std::runtime_error("no face tuple supported for edgemesh"); - break; - } - case PrimitiveType::Tetrahedron: { - throw std::runtime_error("no tet tuple supported for edgemesh"); - break; + return tuple.m_global_cid; } - default: throw std::runtime_error("Invalid primitive type"); break; + case PrimitiveType::Face: + case PrimitiveType::Tetrahedron: + default: throw std::runtime_error("Tuple id: Invalid primitive type"); } } +bool EdgeMesh::is_boundary(const Tuple& tuple) const +{ + return is_boundary_vertex(tuple); +} + +bool EdgeMesh::is_boundary_vertex(const Tuple& vertex) const +{ + assert(is_valid_slow(tuple)); + ConstAccessor ee_accessor = create_const_accessor(m_ee_handle); + return ee_accessor.vector_attribute(tuple)(tuple.m_local_eid) < 0; +} + Tuple EdgeMesh::switch_tuple(const Tuple& tuple, PrimitiveType type) const { - throw std::runtime_error("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); assert(is_valid_slow(tuple)); bool ccw = is_ccw(tuple); - // switch (type) { case PrimitiveType::Vertex: return Tuple( - (tuple.m_local_vid + 1) % (long)2, + 1 - tuple.m_local_vid, tuple.m_local_eid, tuple.m_local_fid, tuple.m_global_cid, tuple.m_hash); - case PrimitiveType::Edge: - // don't know what is the result of the edge's switch, thought we just need vertex_switch? - case PrimitiveType::Face: - case PrimitiveType::Tetrahedron: - default: throw std::runtime_error("Tuple switch: Invalid primitive type"); break; - } -} -bool EdgeMesh::is_ccw(const Tuple&) const -{ - throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); - // we don't need the oriented edge, so it should always be true - return true; -} -bool EdgeMesh::is_boundary(const Tuple& tuple) const -{ - throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); - assert(is_valid_slow(tuple)); - // fix an edge and a vertex, then compute the neighbour edge - ConstAccessor ee_accessor = create_const_accessor(m_ee_handle); - return ee_accessor.vector_attribute(tuple)(tuple.m_local_vid) < 0; -} + case PrimitiveType::Edge: { + const long gvid = id(tuple, PrimitiveType::Vertex); -bool EdgeMesh::is_boundary_vertex(const Tuple& tuple) const -{ - throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); - // boudnary_vertex is a vertex with only one degree - assert(is_valid_slow(tuple)); - ConstAccessor ve_accessor = create_const_accessor(m_ve_handle); - // not sure if it works. - // I think the main problem is I still not sure about the mechanisim of the "id" and "e_tuple" - // funtions. - auto e = ve_accessor.index_access().scalar_attribute(tuple.m_local_vid); - ConstAccessor ev_accessor = create_const_accessor(m_ev_handle); - auto ev = ev_accessor.index_access().vector_attribute(e); - // tuple_from_id(,); - return false; -} + ConstAccessor ee_accessor = create_const_accessor(m_ee_handle); + auto ee = ee_accessor.vector_attribute(tuple); -void EdgeMesh::initialize(Eigen::Ref E) -{ - // resize the EE and VE - RowVectors2l EE; - RowVectors2l VE; - EE.resize(E.rows(), 2); - long max_vid = -1; - for (size_t i = 0; i < E.rows(); i++) { - EE(i, 0) = -1; - EE(i, 1) = -1; - max_vid = std::max(max_vid, E(i, 0)); - max_vid = std::max(max_vid, E(i, 1)); - } - VE.resize(max_vid + 1, 2); - for (size_t i = 0; i < VE.rows(); i++) { - VE(i, 0) = -1; - VE(i, 1) = -1; - } + long gcid_new = ee(tuple.m_local_vid); + long lvid_new = -1; - // compute VE - for (size_t i = 0; i < E.rows(); i++) { - long vid0, vid1; - vid0 = E(i, 0); - vid1 = E(i, 1); - if (VE(vid0, 0) == -1) { - VE(vid0, 0) = i; - } else if (VE(vid0, 1) == -1) { - VE(vid0, 1) = i; - } - if (VE(vid1, 0) == -1) { - VE(vid1, 0) = i; - } else if (VE(vid1, 1) == -1) { - VE(vid1, 1) = i; - } - } + ConstAccessor ev_accessor = create_const_accesor(m_ev_handle); + auto ev = ev_accessor.index_access().vector_attribute(gcid_new); - // compute EE - for (size_t i = 0; i < VE.rows(); i++) { - long eid0 = VE(i, 0); - long eid1 = VE(i, 1); - if (eid0 != -1 && eid1 != -1) { - if (EE(eid0, 0) == -1) { - EE(eid0, 0) = eid1; - } else if (EE(eid1, 0) == -1) { - EE(eid0, 1) = eid1; - } - if (EE(eid1, 0) == -1) { - EE(eid1, 0) = eid0; - } else if (EE(eid1, 0) == -1) { - EE(eid1, 1) = eid0; + for (long i = 0; i < 2; ++i) { + if (ev(i) == gvid) { + lvid_new = i; } } + assert(lvid_new != -1); + + ConstAccessor hash_accessor = get_const_cell_hash_accessor(); + + const Tuple res( + lvid_new, + tuple.m_local_eid, + tuple.m_local_fid, + gcid_new, + get_cell_hash(gcid_new, hash_accessor)); + assert(is_valid(res, hash_accessor)); + return res; + } + case PrimitiveType::Face: + case PrimitiveType::Tetrahedron: + default: throw std::runtime_error("Tuple switch: Invalid primitive type"); break; } +} - initialize(E, EE, VE); +bool EdgeMesh::is_ccw(const Tuple& tuple) const +{ + assert(is_valid_slow(tuple)); + return tuple.m_local_vid == 1; } void EdgeMesh::initialize( - Eigen::Ref EV, - Eigen::Ref EE, - Eigen::Ref VE) + Eigen::Ref EV, + Eigen::Ref EE, + Eigen::Ref VE) { - throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); - std::vector cap{ - static_cast(EV.rows()), - static_cast(EE.rows()), - static_cast(VE.rows())}; + // reserve memory for attributes + + std::vector cap{static_cast(VE.rows()), static_cast(EE.rows())}; set_capacities(cap); - // get Accessors for topology + // get accessors for topology Accessor ev_accessor = create_accessor(m_ev_handle); - Accessor ve_accessor = create_accessor(m_ve_handle); Accessor ee_accessor = create_accessor(m_ee_handle); + Accessor ve_accessor = create_accessor(m_ve_handle); Accessor v_flag_accessor = get_flag_accessor(PrimitiveType::Vertex); Accessor e_flag_accessor = get_flag_accessor(PrimitiveType::Edge); - // wait to add - // ... // iterate over the matrices and fill attributes + for (long i = 0; i < capacity(PrimitiveType::Edge); ++i) { ev_accessor.index_access().vector_attribute(i) = EV.row(i).transpose(); ee_accessor.index_access().vector_attribute(i) = EE.row(i).transpose(); - e_flag_accessor.index_access().scalar_attribute(i) |= 0x1; + e_flag_accessor.index_accessor().scalar_attribtue(i) |= 0x1; } - - // m_vf + // m_ve for (long i = 0; i < capacity(PrimitiveType::Vertex); ++i) { - ve_accessor.index_access().vector_attribute(i) = VE.row(i).transpose(); - // e_flag_accessor.index_access().scalar_attribute(i) |= 0x1; + ve_accessor.index_access().scalar_attribute(i) = VE(i); + v_flag_accesor.index_access().scalar_attribute(i) = |= 0x1; } } -bool EdgeMesh::is_valid(const Tuple& tuple, ConstAccessor& hash_accessor) const +void EdgeMesh::initialize(Eigen::Ref E) { - throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); - // copied from PointMesh.cpp - if (tuple.is_null()) return false; - return true; - return Mesh::is_hash_valid(tuple, hash_accessor); + auto [EE, VE] = edgemesh_topology_initialization(E); + initialize(E, EE, VE); +} + +long EdgeMesh::_debug_id(const Tuple& tuple, PrimitiveType type) +{ + wmtk::logger().warn("This function must only be used for debugging!!"); + return id(tuple, type); } -long EdgeMesh::id(const Tuple& tuple, PrimitiveType type) const +Tuple EdgeMesh::tuple_from_id(const PrimitiveType type, const long gid) const { - throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); switch (type) { case PrimitiveType::Vertex: { - ConstAccessor ev_accessor = create_const_accessor(m_ev_handle); - auto ev = ev_accessor.vector_attribute(tuple); - return ev(tuple.m_local_vid); + return vertex_tuple_from_id(gid); } case PrimitiveType::Edge: { - return tuple.m_global_cid; + return edge_tuple_from_id(gid); } - case PrimitiveType::Face: - case PrimitiveType::Tetrahedron: - default: throw std::runtime_error("Tuple id: Invalid primitive type"); + case PrimitiveType::Face: { + throw std::runtime_error("no tet tuple supported for edgemesh"); + break; + } + case PrimitiveType::Tetrahedron: { + throw std::runtime_error("no tet tuple supported for edgemesh"); + break; + } + default: throw std::runtime_error("Invalid primitive type"); break; } } Tuple EdgeMesh::vertex_tuple_from_id(long id) const { - throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); ConstAccessor ve_accessor = create_const_accessor(m_ve_handle); - // confused about this "id", does this mean the id of vertex or the edge? I refer to the - // TriMesh.cpp(from line 243) auto e = ve_accessor.index_access().scalar_attribute(id); ConstAccessor ev_accessor = create_const_accessor(m_ev_handle); auto ev = ev_accessor.index_access().vector_attribute(e); for (long i = 0; i < 2; ++i) { if (ev(i) == id) { - // assert(autogen::auto_2d_table_complete_vertex[i][0] == i); - // do not know if I use this function right. - Tuple v_tuple = Tuple( - i, - -1, - -1, - e, - get_cell_hash_slow( - e)); // TODO replace by function that takes hash accessor as parameter - assert(is_ccw(v_tuple)); // is_ccw also checks for validity + Tuple v_tuple = Tuple(i, -1, -1, e, get_cell_hash_slow(e)); return v_tuple; } } @@ -237,11 +191,291 @@ Tuple EdgeMesh::vertex_tuple_from_id(long id) const Tuple EdgeMesh::edge_tuple_from_id(long id) const { - throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); - Tuple e_tuple = Tuple(-1, -1, -1, id, get_cell_hash_slow(id)); - assert(is_ccw(e_tuple)); + Tuple e_tuple = Tuple(1, -1, -1, id, get_cell_hash_slow(id)); + assert(is_valid_slow(e_tuple)); return e_tuple; - throw std::runtime_error("edge_tuple_from_id failed"); } + +bool EdgeMesh::is_valid(const Tuple& tuple, ConstAccessor& hash_accessor) const +{ + if (tuple.is_null()) return false; + + if (tuple.m_local_vid < 0 || tuple.m_global_cid < 0) return false; + + return Mesh::is_hash_valid(tuple, hash_accessor); +} + +bool EdgeMesh::is_connectivity_valid() const +{ + // get accessors for topology + ConstAccessor ev_accessor = create_const_accessor(m_ev_handle); + ConstAccessor ee_accessor = create_const_accessor(m_ee_handle); + ConstAccessor ve_accessor = create_const_accessor(m_ve_handle); + ConstAccessor v_flag_accessor = get_flag_accessor(PrimitiveType::Vertex); + ConstAccessor e_flag_accessor = get_flag_accessor(PrimitiveType::Edge); + + // VE and EV + for (long i = 0; i < capacity(PrimitiveType::Vertex); ++i) { + if (v_flag_accessor.index_access().scalar_attribute(i) == 0) { + wmtk::logger().debug("Vertex {} is deleted", i); + continue; + } + int cnt = 0; + for (long j = 0; j < 2; ++j) { + if (ev_accessor.index_access().vector_attribute( + ve_accessor.index_access().scalar_attribute(i))[j] == i) { + cnt++; + } + } + if (cnt == 0) { + return false; + } + } + + // EV and EE + for (long i = 0; i < capacity(PrimitiveType::Edge); ++i) { + if (e_flag_accessor.index_access().scalar_attribute(i) == 0) { + wmtk::logger().debug("Edge {} is deleted", i); + continue; + } + // TODO: need to handle cornor case (self-loop) + } +} + } // namespace wmtk + +// Tuple EdgeMesh::tuple_from_id(const PrimitiveType type, const long gid) const +// { +// throw std::runtime_error("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); +// switch (type) { +// case PrimitiveType::Vertex: { +// return vertex_tuple_from_id(gid); +// } +// case PrimitiveType::Edge: { +// return edge_tuple_from_id(gid); +// } +// case PrimitiveType::Face: { +// throw std::runtime_error("no face tuple supported for edgemesh"); +// break; +// } +// case PrimitiveType::Tetrahedron: { +// throw std::runtime_error("no tet tuple supported for edgemesh"); +// break; +// } +// default: throw std::runtime_error("Invalid primitive type"); break; +// } +// } + +// Tuple EdgeMesh::switch_tuple(const Tuple& tuple, PrimitiveType type) const +// { +// throw std::runtime_error("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); +// assert(is_valid_slow(tuple)); +// bool ccw = is_ccw(tuple); + +// // +// switch (type) { +// case PrimitiveType::Vertex: +// return Tuple( +// (tuple.m_local_vid + 1) % (long)2, +// tuple.m_local_eid, +// tuple.m_local_fid, +// tuple.m_global_cid, +// tuple.m_hash); +// case PrimitiveType::Edge: +// // don't know what is the result of the edge's switch, thought we just need vertex_switch? +// case PrimitiveType::Face: +// case PrimitiveType::Tetrahedron: +// default: throw std::runtime_error("Tuple switch: Invalid primitive type"); break; +// } +// } +// bool EdgeMesh::is_ccw(const Tuple&) const +// { +// throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); +// // we don't need the oriented edge, so it should always be true +// return true; +// } +// bool EdgeMesh::is_boundary(const Tuple& tuple) const +// { +// throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); +// assert(is_valid_slow(tuple)); +// // fix an edge and a vertex, then compute the neighbour edge +// ConstAccessor ee_accessor = create_const_accessor(m_ee_handle); +// return ee_accessor.vector_attribute(tuple)(tuple.m_local_vid) < 0; +// } + +// bool EdgeMesh::is_boundary_vertex(const Tuple& tuple) const +// { +// throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); +// // boudnary_vertex is a vertex with only one degree +// assert(is_valid_slow(tuple)); +// ConstAccessor ve_accessor = create_const_accessor(m_ve_handle); +// // not sure if it works. +// // I think the main problem is I still not sure about the mechanisim of the "id" and "e_tuple" +// // funtions. +// auto e = ve_accessor.index_access().scalar_attribute(tuple.m_local_vid); +// ConstAccessor ev_accessor = create_const_accessor(m_ev_handle); +// auto ev = ev_accessor.index_access().vector_attribute(e); +// // tuple_from_id(,); +// return false; +// } + +// void EdgeMesh::initialize(Eigen::Ref E) +// { +// // resize the EE and VE +// RowVectors2l EE; +// RowVectors2l VE; +// EE.resize(E.rows(), 2); +// long max_vid = -1; +// for (size_t i = 0; i < E.rows(); i++) { +// EE(i, 0) = -1; +// EE(i, 1) = -1; +// max_vid = std::max(max_vid, E(i, 0)); +// max_vid = std::max(max_vid, E(i, 1)); +// } +// VE.resize(max_vid + 1, 2); +// for (size_t i = 0; i < VE.rows(); i++) { +// VE(i, 0) = -1; +// VE(i, 1) = -1; +// } + +// // compute VE +// for (size_t i = 0; i < E.rows(); i++) { +// long vid0, vid1; +// vid0 = E(i, 0); +// vid1 = E(i, 1); +// if (VE(vid0, 0) == -1) { +// VE(vid0, 0) = i; +// } else if (VE(vid0, 1) == -1) { +// VE(vid0, 1) = i; +// } +// if (VE(vid1, 0) == -1) { +// VE(vid1, 0) = i; +// } else if (VE(vid1, 1) == -1) { +// VE(vid1, 1) = i; +// } +// } + +// // compute EE +// for (size_t i = 0; i < VE.rows(); i++) { +// long eid0 = VE(i, 0); +// long eid1 = VE(i, 1); +// if (eid0 != -1 && eid1 != -1) { +// if (EE(eid0, 0) == -1) { +// EE(eid0, 0) = eid1; +// } else if (EE(eid1, 0) == -1) { +// EE(eid0, 1) = eid1; +// } +// if (EE(eid1, 0) == -1) { +// EE(eid1, 0) = eid0; +// } else if (EE(eid1, 0) == -1) { +// EE(eid1, 1) = eid0; +// } +// } +// } + +// initialize(E, EE, VE); +// } + +// void EdgeMesh::initialize( +// Eigen::Ref EV, +// Eigen::Ref EE, +// Eigen::Ref VE) +// { +// throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); +// std::vector cap{ +// static_cast(EV.rows()), +// static_cast(EE.rows()), +// static_cast(VE.rows())}; + +// set_capacities(cap); + +// // get Accessors for topology +// Accessor ev_accessor = create_accessor(m_ev_handle); +// Accessor ve_accessor = create_accessor(m_ve_handle); +// Accessor ee_accessor = create_accessor(m_ee_handle); + +// Accessor v_flag_accessor = get_flag_accessor(PrimitiveType::Vertex); +// Accessor e_flag_accessor = get_flag_accessor(PrimitiveType::Edge); + +// // wait to add +// // ... +// // iterate over the matrices and fill attributes +// for (long i = 0; i < capacity(PrimitiveType::Edge); ++i) { +// ev_accessor.index_access().vector_attribute(i) = EV.row(i).transpose(); +// ee_accessor.index_access().vector_attribute(i) = EE.row(i).transpose(); + +// e_flag_accessor.index_access().scalar_attribute(i) |= 0x1; +// } + +// // m_vf +// for (long i = 0; i < capacity(PrimitiveType::Vertex); ++i) { +// ve_accessor.index_access().vector_attribute(i) = VE.row(i).transpose(); +// // e_flag_accessor.index_access().scalar_attribute(i) |= 0x1; +// } +// } + +// bool EdgeMesh::is_valid(const Tuple& tuple, ConstAccessor& hash_accessor) const +// { +// throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); +// // copied from PointMesh.cpp +// if (tuple.is_null()) return false; +// return true; +// return Mesh::is_hash_valid(tuple, hash_accessor); +// } + +// long EdgeMesh::id(const Tuple& tuple, PrimitiveType type) const +// { +// throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); +// switch (type) { +// case PrimitiveType::Vertex: { +// ConstAccessor ev_accessor = create_const_accessor(m_ev_handle); +// auto ev = ev_accessor.vector_attribute(tuple); +// return ev(tuple.m_local_vid); +// } +// case PrimitiveType::Edge: { +// return tuple.m_global_cid; +// } +// case PrimitiveType::Face: +// case PrimitiveType::Tetrahedron: +// default: throw std::runtime_error("Tuple id: Invalid primitive type"); +// } +// } + +// Tuple EdgeMesh::vertex_tuple_from_id(long id) const +// { +// throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); +// ConstAccessor ve_accessor = create_const_accessor(m_ve_handle); +// // confused about this "id", does this mean the id of vertex or the edge? I refer to the +// // TriMesh.cpp(from line 243) +// auto e = ve_accessor.index_access().scalar_attribute(id); +// ConstAccessor ev_accessor = create_const_accessor(m_ev_handle); +// auto ev = ev_accessor.index_access().vector_attribute(e); +// for (long i = 0; i < 2; ++i) { +// if (ev(i) == id) { +// // assert(autogen::auto_2d_table_complete_vertex[i][0] == i); +// // do not know if I use this function right. +// Tuple v_tuple = Tuple( +// i, +// -1, +// -1, +// e, +// get_cell_hash_slow( +// e)); // TODO replace by function that takes hash accessor as parameter +// assert(is_ccw(v_tuple)); // is_ccw also checks for validity +// return v_tuple; +// } +// } +// throw std::runtime_error("vertex_tuple_from_id failed"); +// } + +// Tuple EdgeMesh::edge_tuple_from_id(long id) const +// { +// throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); +// Tuple e_tuple = Tuple(-1, -1, -1, id, get_cell_hash_slow(id)); +// assert(is_ccw(e_tuple)); +// assert(is_valid_slow(e_tuple)); +// return e_tuple; +// throw std::runtime_error("edge_tuple_from_id failed"); +// } +// } // namespace wmtk diff --git a/src/wmtk/EdgeMesh.hpp b/src/wmtk/EdgeMesh.hpp index 580f4129de..26bb395689 100644 --- a/src/wmtk/EdgeMesh.hpp +++ b/src/wmtk/EdgeMesh.hpp @@ -6,45 +6,50 @@ #include namespace wmtk { -// Simple mesh without topology. Mainly useful for testing attributes without having to construct -// topologies + class EdgeMesh : public Mesh { public: EdgeMesh(); - // EdgeMesh(const EdgeMesh&& o); + EdgeMesh(const EdgeMesh& o); EdgeMesh(EdgeMesh&& o); EdgeMesh& operator=(const EdgeMesh& o); EdgeMesh& operator=(EdgeMesh&& o); - void initialize(Eigen::Ref E); + PrimitiveType top_simplex_type() const override { return PrimitiveType::Edge; } - void initialize( - Eigen::Ref EV, - Eigen::Ref EE, - Eigen::Ref VE); + Tuple split_edge(const Tuple& t, Accessor& hash_accessor) override; + + Tuple collapse_edge(const Tuple& t, Accessor& hash_accessor) override; - PrimitiveType top_simplex_type() const override { return PrimitiveType::Edge; } Tuple switch_tuple(const Tuple& tuple, PrimitiveType type) const override; + bool is_ccw(const Tuple& tuple) const override; bool is_boundary(const Tuple& tuple) const override; bool is_boundary_vertex(const Tuple& tuple) const override; - // TODO: should just write is_boundary(PrimitiveType) - bool is_boundary_edge(const Tuple& tuple) const override { return true; } + void initialize(Eigen::Ref E); - bool is_valid(const Tuple& tuple, ConstAccessor& hash_accessor) const override; + void initialize( + Eigen::Ref EV, + Eigen::Ref EE, + Eigen::Ref VE); - Tuple edge_tuple_from_id(long id) const; - Tuple vertex_tuple_from_id(long id) const; + long _debug_id(const Tuple& tuple, PrimitiveType type) const; + long _debug_id(const Simplex& simplex) const + { + return _debug_id(simplex.tuple(), simplex.primitive_type()); + } - Tuple split_edge(const Tuple&, Accessor&) override { return {}; } - Tuple collapse_edge(const Tuple&, Accessor&) override { return {}; } - bool is_connectivity_valid() const override { return true; } + + bool is_valid(const Tuple& tuple, ConstAccessor& hash_accessor) const override; + + bool is_connectivity_valid() const override; protected: long id(const Tuple& tuple, PrimitiveType type) const override; long id(const Simplex& simplex) const { return id(simplex.tuple(), simplex.primitive_type()); } + long id_vertex(const Tuple& tuple) const { return id(tuple, PrimitiveType::Vertex); } long id_edge(const Tuple& tuple) const { return id(tuple, PrimitiveType::Edge); } @@ -57,15 +62,17 @@ class EdgeMesh : public Mesh */ Tuple tuple_from_id(const PrimitiveType type, const long gid) const override; - // internal structure that encapsulations the actual execution of split and collapse - class EdgeMeshOperationExecutor; - static Tuple with_different_cid(const Tuple& t, long cid); - - - // not sure if it is needed +protected: attribute::MeshAttributeHandle m_ve_handle; + attribute::MeshAttributeHandle m_ev_handle; - attribute::MeshAttributeHandle m_ee_handle; // record relationship between edges + attribute::MeshAttributeHandle m_ee_handle; + + Tuple vertex_tuple_from_id(long id) const; + Tuple edge_tuple_from_id(long id) const; + + // internal structure that encapsulations the actual execution of split and collapse + class EdgeMeshOperationExecutor; }; } // namespace wmtk diff --git a/src/wmtk/TriMesh.cpp b/src/wmtk/TriMesh.cpp index 1a9d847c45..60f47256b3 100644 --- a/src/wmtk/TriMesh.cpp +++ b/src/wmtk/TriMesh.cpp @@ -342,7 +342,7 @@ bool TriMesh::is_connectivity_valid() const cnt++; } } - if (cnt != 1) { + if (cnt == 0) { // std::cout << "EF and FE not compatible" << std::endl; return false; } @@ -361,7 +361,7 @@ bool TriMesh::is_connectivity_valid() const cnt++; } } - if (cnt != 1) { + if (cnt == 0) { // std::cout << "VF and FV not compatible" << std::endl; return false; } diff --git a/src/wmtk/utils/CMakeLists.txt b/src/wmtk/utils/CMakeLists.txt index 3b06117a0c..d3ac765645 100644 --- a/src/wmtk/utils/CMakeLists.txt +++ b/src/wmtk/utils/CMakeLists.txt @@ -2,6 +2,8 @@ set(SRC_FILES Logger.cpp Logger.hpp + edgemesh_topology_initialization.h + edgemesh_topology_initialization.cpp trimesh_topology_initialization.h trimesh_topology_initialization.cpp tetmesh_topology_initialization.h diff --git a/src/wmtk/utils/edgemesh_topology_initialization.cpp b/src/wmtk/utils/edgemesh_topology_initialization.cpp new file mode 100644 index 0000000000..d4636becc0 --- /dev/null +++ b/src/wmtk/utils/edgemesh_topology_initialization.cpp @@ -0,0 +1,52 @@ +#include "edgemesh_topology_initialization.h" +#include +#include +#include + +namespace wmtk { + +std::tuple edgemesh_topology_initialization( + Eigen::Ref E) +{ + RowVectors2l EE; + VectorXl VE; + + long vertex_count = E.maxCoeff() + 1; + + // store the complete vertex-edge connnectivity + std::vector> complete_VE(vertex_count); + + // compute VE + VE.resize(vertex_count, 1); + for (long i = 0; i < E.rows(); ++i) { + for (long j = 0; j < E.cols(); ++j) { + VE[E(i, j)] = i; + complete_VE[E(i, j)].push_back(i); + } + } + + EE.resize(E.rows(), 2); + // compute EE & connectivity check + for (long i = 0; i < complete_VE.size(); ++i) { + assert(complete_VE[i].size() > 0 || complete_VE[i].size() < 3); + if (complete_VE[i].size() == 1) { + // boundary vertex + if (E(complete_VE[i][0], 0) == i) { + EE(complete_VE[i][0], 0) = -1; + } else { + EE(complete_VE[i][0], 1) = -1; + } + } else { + // non-boundary vertex + for (int k = 0; k < 2; ++k) { + if (E(complete_VE[i][k], 0) == i) { + EE(complete_VE[i][k], 0) = complete_VE[i][1 - k]; + } else { + EE(complete_VE[i][k], 1) = complete_VE[i][1 - k]; + } + } + } + } + return {EE, VE}; +} +} // namespace wmtk \ No newline at end of file diff --git a/src/wmtk/utils/edgemesh_topology_initialization.h b/src/wmtk/utils/edgemesh_topology_initialization.h new file mode 100644 index 0000000000..55f85e9b58 --- /dev/null +++ b/src/wmtk/utils/edgemesh_topology_initialization.h @@ -0,0 +1,12 @@ + +#pragma once + +#include + + +namespace wmtk { + +std::tuple edgemesh_topology_initialization( + Eigen::Ref E); // returns {EE, VE} + +} \ No newline at end of file From b6e284458ac8a254b994349a37b02e516f352b48 Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Wed, 27 Sep 2023 16:36:03 -0400 Subject: [PATCH 13/49] take care of the case of self loop --- src/wmtk/EdgeMeshOperationExecutor.cpp | 40 +++++++++++++++++++------- src/wmtk/EdgeMeshOperationExecutor.hpp | 2 +- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/wmtk/EdgeMeshOperationExecutor.cpp b/src/wmtk/EdgeMeshOperationExecutor.cpp index 7cf5593f3b..bf2d475dc6 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.cpp +++ b/src/wmtk/EdgeMeshOperationExecutor.cpp @@ -32,6 +32,10 @@ EdgeMesh::EdgeMeshOperationExecutor::EdgeMeshOperationExecutor( m_neighbor_eids[1] = m_mesh.id_edge(m_mesh.switch_edge(operating_tuple_switch_vertex)); cell_ids_to_update_hash.emplace_back(m_neighbor_eids[1]); } + + if (m_neighbor_eids[0] == m_neighbor_eids[1] && m_neighbor_eids[0] == m_operating_edge_id) { + m_is_self_loop = true; + } } void EdgeMesh::EdgeMeshOperationExecutor::delete_simplices() @@ -87,37 +91,47 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge_single_mesh() simplex_ids_to_delete = get_split_simplices_to_delete(m_operating_tuple, m_mesh); // create new vertex - std::vector new_vids = this->request_simplex_indices(PrimitiveType::Vertex, 1); + const std::vector new_vids = this->request_simplex_indices(PrimitiveType::Vertex, 1); assert(new_vids.size() == 1); const long v_new = new_vids[0]; // create new edges // new_eids[i] is connect to m_neighbor_eids[i] and m_spine_vids[i] - std::vector new_eids = this->request_simplex_indices(PrimitiveType::Edge, 2); + const std::vector new_eids = this->request_simplex_indices(PrimitiveType::Edge, 2); assert(new_eids.size() == 2); - long local_vid = m_mesh.is_ccw(m_operating_tuple) ? 0 : 1; + const long local_vid = m_mesh.is_ccw(m_operating_tuple) ? 0 : 1; // update ee { + // for 2 new edges auto ee_new_0 = ee_accessor.index_access().vector_attribute(new_eids[0]); auto ee_new_1 = ee_accessor.index_access().vector_attribute(new_eids[1]); - ee_new_0[local_vid] = m_neighbor_eids[0]; ee_new_0[(local_vid + 1) % 2] = new_eids[1]; ee_new_1[local_vid] = new_eids[0]; - ee_new_1[(local_vid + 1) % 2] = m_neighbor_eids[1]; - for (long i = 0; i < 2; i++) { - if (m_neighbor_eids[i] != -1) { - auto ee_neighbor = ee_accessor.index_access().vector_attribute(m_neighbor_eids[i]); - for (long j = 0; j < 2; j++) { - if (ee_neighbor[j] == m_operating_edge_id) { - ee_neighbor[j] = new_eids[i]; + if (m_is_self_loop) { + ee_new_0[local_vid] = new_eids[1]; + ee_new_1[(local_vid + 1) % 2] = new_eids[0]; + } else { + ee_new_0[local_vid] = m_neighbor_eids[0]; + ee_new_1[(local_vid + 1) % 2] = m_neighbor_eids[1]; + // for neighbor edges + for (long i = 0; i < 2; i++) { + if (m_neighbor_eids[i] != -1) { + auto ee_neighbor = + ee_accessor.index_access().vector_attribute(m_neighbor_eids[i]); + for (long j = 0; j < 2; j++) { + if (ee_neighbor[j] == m_operating_edge_id) { + ee_neighbor[j] = new_eids[i]; + } } } } } } + // update ev { + // for new edges auto ev_new_0 = ev_accessor.index_access().vector_attribute(new_eids[0]); auto ev_new_1 = ev_accessor.index_access().vector_attribute(new_eids[1]); ev_new_0[local_vid] = m_spine_vids[0]; @@ -125,9 +139,13 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge_single_mesh() ev_new_1[local_vid] = v_new; ev_new_1[(local_vid + 1) % 2] = m_spine_vids[1]; } + // update ve { + // for new vertex ve_accessor.index_access().scalar_attribute(v_new) = new_eids[0]; + + // for spine vertices ve_accessor.index_access().scalar_attribute(m_spine_vids[0]) = new_eids[0]; ve_accessor.index_access().scalar_attribute(m_spine_vids[1]) = new_eids[1]; } diff --git a/src/wmtk/EdgeMeshOperationExecutor.hpp b/src/wmtk/EdgeMeshOperationExecutor.hpp index eb0f83f506..58b45e5b3e 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.hpp +++ b/src/wmtk/EdgeMeshOperationExecutor.hpp @@ -57,7 +57,7 @@ class EdgeMesh::EdgeMeshOperationExecutor private: std::vector prepare_operating_tuples_for_child_meshes() const; void update_hash_in_map(EdgeMesh& child_mesh); - + bool m_is_self_loop = false; // common simplicies std::array m_spine_vids; // V_A_id, V_B_id; std::array m_neighbor_eids = {-1, -1}; From 588530afe4f0534424779d9ce4f1de6e3432ffff Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Wed, 27 Sep 2023 16:59:00 -0400 Subject: [PATCH 14/49] a complete draft of edge mesh operations --- src/wmtk/EdgeMeshOperationExecutor.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/wmtk/EdgeMeshOperationExecutor.cpp b/src/wmtk/EdgeMeshOperationExecutor.cpp index bf2d475dc6..7a66833f2a 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.cpp +++ b/src/wmtk/EdgeMeshOperationExecutor.cpp @@ -122,6 +122,7 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge_single_mesh() for (long j = 0; j < 2; j++) { if (ee_neighbor[j] == m_operating_edge_id) { ee_neighbor[j] = new_eids[i]; + break; // must break here } } } @@ -171,8 +172,8 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge() Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge_single_mesh() { // check if the collapse is valid - if (m_mesh.is_boundary(m_operating_tuple) && - m_mesh.is_boundary(m_mesh.switch_vertex(m_operating_tuple))) { + if (m_is_self_loop || (m_mesh.is_boundary(m_operating_tuple) && + m_mesh.is_boundary(m_mesh.switch_vertex(m_operating_tuple)))) { return Tuple(); } @@ -180,12 +181,14 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge_single_mesh() // update ee { + // for neighbor edges for (long i = 0; i < 2; i++) { if (m_neighbor_eids[i] != -1) { auto ee_neighbor = ee_accessor.index_access().vector_attribute(m_neighbor_eids[i]); for (long j = 0; j < 2; j++) { if (ee_neighbor[j] == m_operating_edge_id) { ee_neighbor[j] = m_neighbor_eids[(i + 1) % 2]; + break; } } } @@ -194,17 +197,26 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge_single_mesh() // update ev { - // TODO: implement this + if (m_neighbor_eids[1] != -1) { + auto ev_neighbor = ev_accessor.index_access().vector_attribute(m_neighbor_eids[1]); + for (long j = 0; j < 2; j++) { + if (ev_neighbor[j] == m_spine_vids[1]) { + ev_neighbor[j] = m_spine_vids[0]; + } + } + } } // update ve { - // TODO: implement this + ve_accessor.index_access().scalar_attribute(m_spine_vids[0]) = m_neighbor_eids[1]; } update_cell_hash(); delete_simplices(); - return Tuple(); + + const long ret_eid = m_neighbor_eids[0] == -1 ? m_neighbor_eids[1] : m_neighbor_eids[0]; + return m_mesh.edge_tuple_from_id(ret_eid); } std::vector EdgeMesh::EdgeMeshOperationExecutor::request_simplex_indices( From b006e3007298b37c6072c08c053052f4da4bea75 Mon Sep 17 00:00:00 2001 From: JcDai Date: Wed, 27 Sep 2023 17:07:50 -0400 Subject: [PATCH 15/49] implemented edge mesh --- src/wmtk/EdgeMesh.cpp | 30 +++++++++++------- src/wmtk/EdgeMesh.hpp | 4 +++ tests/test_topology.cpp | 57 ++++++++++++++++++++++++++++++++++ tests/tools/DEBUG_EdgeMesh.hpp | 2 +- 4 files changed, 81 insertions(+), 12 deletions(-) diff --git a/src/wmtk/EdgeMesh.cpp b/src/wmtk/EdgeMesh.cpp index 2cd95d6e2d..70d1345eae 100644 --- a/src/wmtk/EdgeMesh.cpp +++ b/src/wmtk/EdgeMesh.cpp @@ -1,4 +1,10 @@ #include "EdgeMesh.hpp" + + +#include +#include +#include +#include namespace wmtk { EdgeMesh::EdgeMesh() : Mesh(1) @@ -23,13 +29,13 @@ Tuple EdgeMesh::collapse_edge(const Tuple& t, Accessor& hash_accessor) return Tuple(); } -long EdgeMesh::id(const Tuple& tuple, PrimitiveType) const +long EdgeMesh::id(const Tuple& tuple, PrimitiveType type) const { switch (type) { case PrimitiveType::Vertex: { ConstAccessor ev_accessor = create_const_accessor(m_ev_handle); - auto ev = ev_accessor.vertex_attribute(tuple); - return fv(tuple.m_local_vid); + auto ev = ev_accessor.vector_attribute(tuple); + return ev(tuple.m_local_vid); } case PrimitiveType::Edge: { return tuple.m_global_cid; @@ -45,7 +51,7 @@ bool EdgeMesh::is_boundary(const Tuple& tuple) const return is_boundary_vertex(tuple); } -bool EdgeMesh::is_boundary_vertex(const Tuple& vertex) const +bool EdgeMesh::is_boundary_vertex(const Tuple& tuple) const { assert(is_valid_slow(tuple)); ConstAccessor ee_accessor = create_const_accessor(m_ee_handle); @@ -74,7 +80,7 @@ Tuple EdgeMesh::switch_tuple(const Tuple& tuple, PrimitiveType type) const long gcid_new = ee(tuple.m_local_vid); long lvid_new = -1; - ConstAccessor ev_accessor = create_const_accesor(m_ev_handle); + ConstAccessor ev_accessor = create_const_accessor(m_ev_handle); auto ev = ev_accessor.index_access().vector_attribute(gcid_new); for (long i = 0; i < 2; ++i) { @@ -108,8 +114,8 @@ bool EdgeMesh::is_ccw(const Tuple& tuple) const } void EdgeMesh::initialize( - Eigen::Ref EV, - Eigen::Ref EE, + Eigen::Ref EV, + Eigen::Ref EE, Eigen::Ref VE) { // reserve memory for attributes @@ -132,22 +138,22 @@ void EdgeMesh::initialize( ev_accessor.index_access().vector_attribute(i) = EV.row(i).transpose(); ee_accessor.index_access().vector_attribute(i) = EE.row(i).transpose(); - e_flag_accessor.index_accessor().scalar_attribtue(i) |= 0x1; + e_flag_accessor.index_access().scalar_attribute(i) |= 0x1; } // m_ve for (long i = 0; i < capacity(PrimitiveType::Vertex); ++i) { ve_accessor.index_access().scalar_attribute(i) = VE(i); - v_flag_accesor.index_access().scalar_attribute(i) = |= 0x1; + v_flag_accessor.index_access().scalar_attribute(i) |= 0x1; } } -void EdgeMesh::initialize(Eigen::Ref E) +void EdgeMesh::initialize(Eigen::Ref E) { auto [EE, VE] = edgemesh_topology_initialization(E); initialize(E, EE, VE); } -long EdgeMesh::_debug_id(const Tuple& tuple, PrimitiveType type) +long EdgeMesh::_debug_id(const Tuple& tuple, PrimitiveType type) const { wmtk::logger().warn("This function must only be used for debugging!!"); return id(tuple, type); @@ -241,6 +247,8 @@ bool EdgeMesh::is_connectivity_valid() const } // TODO: need to handle cornor case (self-loop) } + + return true; } } // namespace wmtk diff --git a/src/wmtk/EdgeMesh.hpp b/src/wmtk/EdgeMesh.hpp index 26bb395689..f1996cd2df 100644 --- a/src/wmtk/EdgeMesh.hpp +++ b/src/wmtk/EdgeMesh.hpp @@ -27,6 +27,10 @@ class EdgeMesh : public Mesh bool is_ccw(const Tuple& tuple) const override; bool is_boundary(const Tuple& tuple) const override; bool is_boundary_vertex(const Tuple& tuple) const override; + bool is_boundary_edge(const Tuple& tuple) const override + { + throw("This function doesn't make sense for edgemesh"); + } void initialize(Eigen::Ref E); diff --git a/tests/test_topology.cpp b/tests/test_topology.cpp index c1e6e3ccd5..1f22cfed92 100644 --- a/tests/test_topology.cpp +++ b/tests/test_topology.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -334,3 +335,59 @@ TEST_CASE("topology_of_tet_bunny", "[topology][3D]") } } } + +TEST_CASE("topology_of_single_line", "[topology][1D]") +{ + Eigen::Matrix E; + E << 0, 1; + auto [EE, VE] = edgemesh_topology_initialization(E); + + std::cout << "EV:\n" << E << std::endl; + std::cout << "EE:\n" << EE << std::endl; + std::cout << "VE:\n" << VE << std::endl; + + // 1. Test relationship between VE and EV + for (int i = 0; i < VE.size(); ++i) { + CHECK((E.row(VE(i)).array() == i).any()); + } + + // 2. Test relationship between EV and EE + for (int i = 0; i < EE.rows(); ++i) { + for (int j = 0; j < 2; ++j) { + long nb = EE(i, j); + if (nb < 0) continue; + + CHECK((EE.row(nb).array() == i).any()); + + // TODO add checks + } + } +} + +TEST_CASE("topology_of_multiple_lines", "[topology][1D]") +{ + Eigen::Matrix E; + E << 0, 1, 1, 4, 3, 4, 2, 0, 5, 2; + auto [EE, VE] = edgemesh_topology_initialization(E); + + std::cout << "EV:\n" << E << std::endl; + std::cout << "EE:\n" << EE << std::endl; + std::cout << "VE:\n" << VE << std::endl; + + // 1. Test relationship between VE and EV + for (int i = 0; i < VE.size(); ++i) { + CHECK((E.row(VE(i)).array() == i).any()); + } + + // 2. Test relationship between EV and EE + for (int i = 0; i < EE.rows(); ++i) { + for (int j = 0; j < 2; ++j) { + long nb = EE(i, j); + if (nb < 0) continue; + + CHECK((EE.row(nb).array() == i).any()); + + // TODO add checks + } + } +} \ No newline at end of file diff --git a/tests/tools/DEBUG_EdgeMesh.hpp b/tests/tools/DEBUG_EdgeMesh.hpp index ba87b7de35..0c867ed8de 100644 --- a/tests/tools/DEBUG_EdgeMesh.hpp +++ b/tests/tools/DEBUG_EdgeMesh.hpp @@ -7,7 +7,7 @@ class DEBUG_EdgeMesh : public EdgeMesh { public: using EdgeMesh::EdgeMesh; - // DEBUG_EdgeMesh(const EdgeMesh& m); + DEBUG_EdgeMesh(const EdgeMesh& m); DEBUG_EdgeMesh(EdgeMesh&& m); using EdgeMesh::operator=; From 1a91445d469c1dc1b90d44d690c9e768837b70a7 Mon Sep 17 00:00:00 2001 From: JcDai Date: Wed, 27 Sep 2023 17:15:39 -0400 Subject: [PATCH 16/49] add 1d topology unit test --- tests/test_topology.cpp | 49 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/tests/test_topology.cpp b/tests/test_topology.cpp index 1f22cfed92..3bd26af6b6 100644 --- a/tests/test_topology.cpp +++ b/tests/test_topology.cpp @@ -338,13 +338,16 @@ TEST_CASE("topology_of_tet_bunny", "[topology][3D]") TEST_CASE("topology_of_single_line", "[topology][1D]") { + /* + 0 ---- 1 + */ Eigen::Matrix E; E << 0, 1; auto [EE, VE] = edgemesh_topology_initialization(E); - std::cout << "EV:\n" << E << std::endl; - std::cout << "EE:\n" << EE << std::endl; - std::cout << "VE:\n" << VE << std::endl; + // std::cout << "EV:\n" << E << std::endl; + // std::cout << "EE:\n" << EE << std::endl; + // std::cout << "VE:\n" << VE << std::endl; // 1. Test relationship between VE and EV for (int i = 0; i < VE.size(); ++i) { @@ -366,13 +369,47 @@ TEST_CASE("topology_of_single_line", "[topology][1D]") TEST_CASE("topology_of_multiple_lines", "[topology][1D]") { + /* + 5 -- 2 -- 0 -- 1 -- 4 -- 3 + */ Eigen::Matrix E; E << 0, 1, 1, 4, 3, 4, 2, 0, 5, 2; auto [EE, VE] = edgemesh_topology_initialization(E); - std::cout << "EV:\n" << E << std::endl; - std::cout << "EE:\n" << EE << std::endl; - std::cout << "VE:\n" << VE << std::endl; + // std::cout << "EV:\n" << E << std::endl; + // std::cout << "EE:\n" << EE << std::endl; + // std::cout << "VE:\n" << VE << std::endl; + + // 1. Test relationship between VE and EV + for (int i = 0; i < VE.size(); ++i) { + CHECK((E.row(VE(i)).array() == i).any()); + } + + // 2. Test relationship between EV and EE + for (int i = 0; i < EE.rows(); ++i) { + for (int j = 0; j < 2; ++j) { + long nb = EE(i, j); + if (nb < 0) continue; + + CHECK((EE.row(nb).array() == i).any()); + + // TODO add checks + } + } +} + +TEST_CASE("topology_of_loop", "[topology][1D]") +{ + /* + 5 -- 2 -- 0 -- 1 -- 4 -- 3 -- 5* + */ + Eigen::Matrix E; + E << 0, 1, 1, 4, 3, 4, 2, 0, 5, 2, 5, 3; + auto [EE, VE] = edgemesh_topology_initialization(E); + + // std::cout << "EV:\n" << E << std::endl; + // std::cout << "EE:\n" << EE << std::endl; + // std::cout << "VE:\n" << VE << std::endl; // 1. Test relationship between VE and EV for (int i = 0; i < VE.size(); ++i) { From 7f9f17814e9f6796680ca1327430d636f57121ee Mon Sep 17 00:00:00 2001 From: JcDai Date: Wed, 27 Sep 2023 17:19:45 -0400 Subject: [PATCH 17/49] add implementation for operations in edgemesh clas --- src/wmtk/EdgeMesh.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/wmtk/EdgeMesh.cpp b/src/wmtk/EdgeMesh.cpp index 70d1345eae..cfb4c04140 100644 --- a/src/wmtk/EdgeMesh.cpp +++ b/src/wmtk/EdgeMesh.cpp @@ -19,14 +19,14 @@ EdgeMesh& EdgeMesh::operator=(EdgeMesh&& o) = default; Tuple EdgeMesh::split_edge(const Tuple& t, Accessor& hash_accessor) { - // TODO: to be implemented after operations - return Tuple(); + EdgeMesh::EdgeMeshOperationExecutor executor(*this, t, hash_accessor); + return executor.split_edge(); } Tuple EdgeMesh::collapse_edge(const Tuple& t, Accessor& hash_accessor) { - // TODO: to be implemented after operations - return Tuple(); + EdgeMesh::EdgeMeshOperationExecutor executor(*this, t, hash_accessor); + return executor.collapse(); } long EdgeMesh::id(const Tuple& tuple, PrimitiveType type) const From 0f1e5c4a2f9226445b814dbc941d15ba7ec53009 Mon Sep 17 00:00:00 2001 From: JcDai Date: Wed, 27 Sep 2023 17:25:40 -0400 Subject: [PATCH 18/49] fix typo --- src/wmtk/EdgeMesh.cpp | 2 +- tests/CMakeLists.txt | 1 + tests/test_tuple_1d.cpp | 0 3 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 tests/test_tuple_1d.cpp diff --git a/src/wmtk/EdgeMesh.cpp b/src/wmtk/EdgeMesh.cpp index cfb4c04140..009ce0aa61 100644 --- a/src/wmtk/EdgeMesh.cpp +++ b/src/wmtk/EdgeMesh.cpp @@ -26,7 +26,7 @@ Tuple EdgeMesh::split_edge(const Tuple& t, Accessor& hash_accessor) Tuple EdgeMesh::collapse_edge(const Tuple& t, Accessor& hash_accessor) { EdgeMesh::EdgeMeshOperationExecutor executor(*this, t, hash_accessor); - return executor.collapse(); + return executor.collapse_edge(); } long EdgeMesh::id(const Tuple& tuple, PrimitiveType type) const diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f5102c7272..f1d6e33e1a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -11,6 +11,7 @@ lagrange_include_modules(io) set(TEST_SOURCES test_topology.cpp test_tuple.cpp + test_tuple_1d.cpp test_tuple_2d.cpp test_tuple_3d.cpp test_io.cpp diff --git a/tests/test_tuple_1d.cpp b/tests/test_tuple_1d.cpp new file mode 100644 index 0000000000..e69de29bb2 From 4b549e2d2cb4218cf22a220e822de5564b414963 Mon Sep 17 00:00:00 2001 From: JcDai Date: Wed, 27 Sep 2023 17:39:29 -0400 Subject: [PATCH 19/49] add debug_edgemesh examples --- tests/test_tuple_1d.cpp | 41 ++++++++++++++++++++++ tests/tools/DEBUG_EdgeMesh.cpp | 9 +---- tests/tools/EdgeMesh_examples.cpp | 58 +++++++++++++++++++++++-------- tests/tools/EdgeMesh_examples.hpp | 28 +++++++++++++-- 4 files changed, 112 insertions(+), 24 deletions(-) diff --git a/tests/test_tuple_1d.cpp b/tests/test_tuple_1d.cpp index e69de29bb2..9b5a62a4e9 100644 --- a/tests/test_tuple_1d.cpp +++ b/tests/test_tuple_1d.cpp @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#include "tools/DEBUG_EdgeMesh.hpp" +#include "tools/EdgeMesh_examples.hpp" + +using namespace wmtk; +using namespace wmtk::tests; + +TEST_CASE("1D_initialize", "[mesh_creation],[tuple_1d]") +{ + DEBUG_EdgeMesh m; + RowVectors2l edges; + edges.resize(1, 2); + edges << 0, 1; + + SECTION("init with FV, FE, FF, VF, EF") + { + m = single_triangle(); + } + SECTION("init directly from RowVectors3l") + { + m.initialize(tris); + } + + const std::vector vertices = m.get_all(PrimitiveType::Vertex); + REQUIRE(vertices.size() == 3); + const std::vector edges = m.get_all(PrimitiveType::Edge); + REQUIRE(edges.size() == 3); + const std::vector faces = m.get_all(PrimitiveType::Face); + REQUIRE(faces.size() == 1); + + + REQUIRE(m.is_connectivity_valid()); + + const Tuple t = m.get_all(PrimitiveType::Face)[0]; + REQUIRE(m.is_valid_slow(t)); +} \ No newline at end of file diff --git a/tests/tools/DEBUG_EdgeMesh.cpp b/tests/tools/DEBUG_EdgeMesh.cpp index 621e71a042..293763046b 100644 --- a/tests/tools/DEBUG_EdgeMesh.cpp +++ b/tests/tools/DEBUG_EdgeMesh.cpp @@ -59,14 +59,7 @@ auto DEBUG_EdgeMesh::edge_tuple_from_vids(const long v1, const long v2) const -> } } if (local_vid1 != -1 && local_vid2 != -1) { - // unsure for this s function - // - // return Tuple( - // local_vid1, - // (3 - local_vid1 - local_vid2) % 3, - // -1, - // eid, - // get_cell_hash_slow(eid)); + return Tuple(local_vid1, -1, -1, eid, get_cell_hash_slow(eid)); } } return Tuple(); diff --git a/tests/tools/EdgeMesh_examples.cpp b/tests/tools/EdgeMesh_examples.cpp index f62f42c53b..8540c06aed 100644 --- a/tests/tools/EdgeMesh_examples.cpp +++ b/tests/tools/EdgeMesh_examples.cpp @@ -2,44 +2,74 @@ namespace wmtk::tests { -EdgeMesh simple_line() +EdgeMesh single_line() { EdgeMesh m; RowVectors2l edges; - edges.resize(4, 2); + edges.resize(1, 2); + edges.row(0) << 0, 1; - edges.row(1) << 1, 2; - edges.row(2) << 2, 3; - edges.row(3) << 3, 4; + m.initialize(edges); return m; } -EdgeMesh loop_line() + +EdgeMesh multiple_lines() { EdgeMesh m; RowVectors2l edges; - edges.resize(4, 2); + edges.resize(5, 2); + edges.row(0) << 0, 1; edges.row(1) << 1, 2; edges.row(2) << 2, 3; - edges.row(3) << 3, 0; + edges.row(3) << 3, 4; + edges.row(4) << 4, 5; + m.initialize(edges); return m; } -EdgeMesh multiple_lines() + +EdgeMesh loop_lines() { EdgeMesh m; RowVectors2l edges; - edges.resize(8, 2); + edges.resize(6, 2); + edges.row(0) << 0, 1; edges.row(1) << 1, 2; edges.row(2) << 2, 3; edges.row(3) << 3, 4; - edges.row(4) << 5, 6; - edges.row(5) << 6, 7; - edges.row(6) << 7, 8; - edges.row(7) << 8, 9; + edges.row(4) << 4, 5; + edges.row(5) << 5, 0; + + m.initialize(edges); + return m; +} + +EdgeMesh self_loop() +{ + EdgeMesh m; + RowVectors2l edges; + + edges.resize(1, 2); + edges.row(0) << 0, 0; + m.initialize(edges); return m; } + +EdgeMesh two_line_loop() +{ + EdgeMesh m; + RowVectors2l edges; + edges.resize(2, 2); + + edges.row(0) << 0, 1; + edges.row(1) << 1, 0; + + m.initialize(edges); + return m; +} + } // namespace wmtk::tests \ No newline at end of file diff --git a/tests/tools/EdgeMesh_examples.hpp b/tests/tools/EdgeMesh_examples.hpp index eb71c91ce5..61abc82cc4 100644 --- a/tests/tools/EdgeMesh_examples.hpp +++ b/tests/tools/EdgeMesh_examples.hpp @@ -3,7 +3,31 @@ #include namespace wmtk::tests { -EdgeMesh simple_line(); -EdgeMesh loop_line(); + +/* + 0 --- 1 +*/ +EdgeMesh single_line(); + +/* + 0 -- 1 -- 2 -- 3 -- 4 -- 5 +*/ EdgeMesh multiple_lines(); + +/* + 0 -- 1 -- 2 -- 3 -- 4 -- 5 -- 0* +*/ + +EdgeMesh loop_lines(); + +/* + 0 --- 0 +*/ +EdgeMesh self_loop(); + +/* + 0 -- 1 -- 0* +*/ +EdgeMesh two_line_loop(); + } // namespace wmtk::tests \ No newline at end of file From d6f79e0d818af8b95083e14aaf72f361ea292b7f Mon Sep 17 00:00:00 2001 From: JcDai Date: Wed, 27 Sep 2023 17:40:45 -0400 Subject: [PATCH 20/49] fix bug --- tests/test_1d_operations.cpp | 8 -------- tests/test_tuple_1d.cpp | 30 +----------------------------- 2 files changed, 1 insertion(+), 37 deletions(-) diff --git a/tests/test_1d_operations.cpp b/tests/test_1d_operations.cpp index 15cd467320..e256e9b7c8 100644 --- a/tests/test_1d_operations.cpp +++ b/tests/test_1d_operations.cpp @@ -19,11 +19,3 @@ using TMOE = decltype(std::declval().get_tmoe( constexpr PrimitiveType PV = PrimitiveType::Vertex; constexpr PrimitiveType PE = PrimitiveType::Edge; - -TEST_CASE("1D_initialize", "[operations][1D]") -{ - // DEBUG_EdgeMesh; - DEBUG_EdgeMesh mesh0 = simple_line(); - DEBUG_EdgeMesh mesh1 = loop_line(); - DEBUG_EdgeMesh mesh2 = multiple_lines(); -} \ No newline at end of file diff --git a/tests/test_tuple_1d.cpp b/tests/test_tuple_1d.cpp index 9b5a62a4e9..a1dcbd7d87 100644 --- a/tests/test_tuple_1d.cpp +++ b/tests/test_tuple_1d.cpp @@ -10,32 +10,4 @@ using namespace wmtk; using namespace wmtk::tests; -TEST_CASE("1D_initialize", "[mesh_creation],[tuple_1d]") -{ - DEBUG_EdgeMesh m; - RowVectors2l edges; - edges.resize(1, 2); - edges << 0, 1; - - SECTION("init with FV, FE, FF, VF, EF") - { - m = single_triangle(); - } - SECTION("init directly from RowVectors3l") - { - m.initialize(tris); - } - - const std::vector vertices = m.get_all(PrimitiveType::Vertex); - REQUIRE(vertices.size() == 3); - const std::vector edges = m.get_all(PrimitiveType::Edge); - REQUIRE(edges.size() == 3); - const std::vector faces = m.get_all(PrimitiveType::Face); - REQUIRE(faces.size() == 1); - - - REQUIRE(m.is_connectivity_valid()); - - const Tuple t = m.get_all(PrimitiveType::Face)[0]; - REQUIRE(m.is_valid_slow(t)); -} \ No newline at end of file +TEST_CASE("1D_initialize", "[mesh_creation],[tuple_1d]") {} \ No newline at end of file From 51e750d2fd95ae9c4e76622a43438660652af54d Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Wed, 27 Sep 2023 17:58:55 -0400 Subject: [PATCH 21/49] rename tmoe to emoe --- tests/test_1d_operations.cpp | 10 +++++++++- tests/tools/DEBUG_EdgeMesh.cpp | 2 +- tests/tools/DEBUG_EdgeMesh.hpp | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/test_1d_operations.cpp b/tests/test_1d_operations.cpp index e256e9b7c8..861d5a13c9 100644 --- a/tests/test_1d_operations.cpp +++ b/tests/test_1d_operations.cpp @@ -13,9 +13,17 @@ using namespace wmtk::tests; using EM = EdgeMesh; using MapResult = typename Eigen::Matrix::MapType; -using TMOE = decltype(std::declval().get_tmoe( +using EMOE = decltype(std::declval().get_emoe( wmtk::Tuple(), std::declval&>())); constexpr PrimitiveType PV = PrimitiveType::Vertex; constexpr PrimitiveType PE = PrimitiveType::Edge; + +TEST_CASE("edge_mesh", "[operations][1D]") +{ + SECTION("single line") + { + REQUIRE(true); + } +} \ No newline at end of file diff --git a/tests/tools/DEBUG_EdgeMesh.cpp b/tests/tools/DEBUG_EdgeMesh.cpp index 293763046b..def5315aa1 100644 --- a/tests/tools/DEBUG_EdgeMesh.cpp +++ b/tests/tools/DEBUG_EdgeMesh.cpp @@ -113,7 +113,7 @@ Accessor DEBUG_EdgeMesh::get_cell_hash_accessor() /** * @brief returns the EdgeMeshOperationExecutor */ -auto DEBUG_EdgeMesh::get_tmoe(const Tuple& t, Accessor& hash_accessor) +auto DEBUG_EdgeMesh::get_emoe(const Tuple& t, Accessor& hash_accessor) -> EdgeMeshOperationExecutor { return EdgeMeshOperationExecutor(*this, t, hash_accessor); diff --git a/tests/tools/DEBUG_EdgeMesh.hpp b/tests/tools/DEBUG_EdgeMesh.hpp index 0c867ed8de..3f2300d0b4 100644 --- a/tests/tools/DEBUG_EdgeMesh.hpp +++ b/tests/tools/DEBUG_EdgeMesh.hpp @@ -61,7 +61,7 @@ class DEBUG_EdgeMesh : public EdgeMesh Accessor get_cell_hash_accessor(); - EdgeMeshOperationExecutor get_tmoe(const Tuple& t, Accessor& hash_accessor); + EdgeMeshOperationExecutor get_emoe(const Tuple& t, Accessor& hash_accessor); }; } // namespace wmtk::tests From 9d210e50a2bc26615534b426add933513b83aded Mon Sep 17 00:00:00 2001 From: JcDai Date: Wed, 27 Sep 2023 18:05:05 -0400 Subject: [PATCH 22/49] add 1d tuple tests --- src/wmtk/EdgeMesh.cpp | 235 ---------------------------------------- tests/test_tuple_1d.cpp | 141 +++++++++++++++++++++++- 2 files changed, 140 insertions(+), 236 deletions(-) diff --git a/src/wmtk/EdgeMesh.cpp b/src/wmtk/EdgeMesh.cpp index 009ce0aa61..a4177c716e 100644 --- a/src/wmtk/EdgeMesh.cpp +++ b/src/wmtk/EdgeMesh.cpp @@ -252,238 +252,3 @@ bool EdgeMesh::is_connectivity_valid() const } } // namespace wmtk - -// Tuple EdgeMesh::tuple_from_id(const PrimitiveType type, const long gid) const -// { -// throw std::runtime_error("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); -// switch (type) { -// case PrimitiveType::Vertex: { -// return vertex_tuple_from_id(gid); -// } -// case PrimitiveType::Edge: { -// return edge_tuple_from_id(gid); -// } -// case PrimitiveType::Face: { -// throw std::runtime_error("no face tuple supported for edgemesh"); -// break; -// } -// case PrimitiveType::Tetrahedron: { -// throw std::runtime_error("no tet tuple supported for edgemesh"); -// break; -// } -// default: throw std::runtime_error("Invalid primitive type"); break; -// } -// } - -// Tuple EdgeMesh::switch_tuple(const Tuple& tuple, PrimitiveType type) const -// { -// throw std::runtime_error("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); -// assert(is_valid_slow(tuple)); -// bool ccw = is_ccw(tuple); - -// // -// switch (type) { -// case PrimitiveType::Vertex: -// return Tuple( -// (tuple.m_local_vid + 1) % (long)2, -// tuple.m_local_eid, -// tuple.m_local_fid, -// tuple.m_global_cid, -// tuple.m_hash); -// case PrimitiveType::Edge: -// // don't know what is the result of the edge's switch, thought we just need vertex_switch? -// case PrimitiveType::Face: -// case PrimitiveType::Tetrahedron: -// default: throw std::runtime_error("Tuple switch: Invalid primitive type"); break; -// } -// } -// bool EdgeMesh::is_ccw(const Tuple&) const -// { -// throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); -// // we don't need the oriented edge, so it should always be true -// return true; -// } -// bool EdgeMesh::is_boundary(const Tuple& tuple) const -// { -// throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); -// assert(is_valid_slow(tuple)); -// // fix an edge and a vertex, then compute the neighbour edge -// ConstAccessor ee_accessor = create_const_accessor(m_ee_handle); -// return ee_accessor.vector_attribute(tuple)(tuple.m_local_vid) < 0; -// } - -// bool EdgeMesh::is_boundary_vertex(const Tuple& tuple) const -// { -// throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); -// // boudnary_vertex is a vertex with only one degree -// assert(is_valid_slow(tuple)); -// ConstAccessor ve_accessor = create_const_accessor(m_ve_handle); -// // not sure if it works. -// // I think the main problem is I still not sure about the mechanisim of the "id" and "e_tuple" -// // funtions. -// auto e = ve_accessor.index_access().scalar_attribute(tuple.m_local_vid); -// ConstAccessor ev_accessor = create_const_accessor(m_ev_handle); -// auto ev = ev_accessor.index_access().vector_attribute(e); -// // tuple_from_id(,); -// return false; -// } - -// void EdgeMesh::initialize(Eigen::Ref E) -// { -// // resize the EE and VE -// RowVectors2l EE; -// RowVectors2l VE; -// EE.resize(E.rows(), 2); -// long max_vid = -1; -// for (size_t i = 0; i < E.rows(); i++) { -// EE(i, 0) = -1; -// EE(i, 1) = -1; -// max_vid = std::max(max_vid, E(i, 0)); -// max_vid = std::max(max_vid, E(i, 1)); -// } -// VE.resize(max_vid + 1, 2); -// for (size_t i = 0; i < VE.rows(); i++) { -// VE(i, 0) = -1; -// VE(i, 1) = -1; -// } - -// // compute VE -// for (size_t i = 0; i < E.rows(); i++) { -// long vid0, vid1; -// vid0 = E(i, 0); -// vid1 = E(i, 1); -// if (VE(vid0, 0) == -1) { -// VE(vid0, 0) = i; -// } else if (VE(vid0, 1) == -1) { -// VE(vid0, 1) = i; -// } -// if (VE(vid1, 0) == -1) { -// VE(vid1, 0) = i; -// } else if (VE(vid1, 1) == -1) { -// VE(vid1, 1) = i; -// } -// } - -// // compute EE -// for (size_t i = 0; i < VE.rows(); i++) { -// long eid0 = VE(i, 0); -// long eid1 = VE(i, 1); -// if (eid0 != -1 && eid1 != -1) { -// if (EE(eid0, 0) == -1) { -// EE(eid0, 0) = eid1; -// } else if (EE(eid1, 0) == -1) { -// EE(eid0, 1) = eid1; -// } -// if (EE(eid1, 0) == -1) { -// EE(eid1, 0) = eid0; -// } else if (EE(eid1, 0) == -1) { -// EE(eid1, 1) = eid0; -// } -// } -// } - -// initialize(E, EE, VE); -// } - -// void EdgeMesh::initialize( -// Eigen::Ref EV, -// Eigen::Ref EE, -// Eigen::Ref VE) -// { -// throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); -// std::vector cap{ -// static_cast(EV.rows()), -// static_cast(EE.rows()), -// static_cast(VE.rows())}; - -// set_capacities(cap); - -// // get Accessors for topology -// Accessor ev_accessor = create_accessor(m_ev_handle); -// Accessor ve_accessor = create_accessor(m_ve_handle); -// Accessor ee_accessor = create_accessor(m_ee_handle); - -// Accessor v_flag_accessor = get_flag_accessor(PrimitiveType::Vertex); -// Accessor e_flag_accessor = get_flag_accessor(PrimitiveType::Edge); - -// // wait to add -// // ... -// // iterate over the matrices and fill attributes -// for (long i = 0; i < capacity(PrimitiveType::Edge); ++i) { -// ev_accessor.index_access().vector_attribute(i) = EV.row(i).transpose(); -// ee_accessor.index_access().vector_attribute(i) = EE.row(i).transpose(); - -// e_flag_accessor.index_access().scalar_attribute(i) |= 0x1; -// } - -// // m_vf -// for (long i = 0; i < capacity(PrimitiveType::Vertex); ++i) { -// ve_accessor.index_access().vector_attribute(i) = VE.row(i).transpose(); -// // e_flag_accessor.index_access().scalar_attribute(i) |= 0x1; -// } -// } - -// bool EdgeMesh::is_valid(const Tuple& tuple, ConstAccessor& hash_accessor) const -// { -// throw("this function has not been implemented! -- EdgeMesh.hpp/EdgeMesh.cpp"); -// // copied from PointMesh.cpp -// if (tuple.is_null()) return false; -// return true; -// return Mesh::is_hash_valid(tuple, hash_accessor); -// } - -// long EdgeMesh::id(const Tuple& tuple, PrimitiveType type) const -// { -// throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); -// switch (type) { -// case PrimitiveType::Vertex: { -// ConstAccessor ev_accessor = create_const_accessor(m_ev_handle); -// auto ev = ev_accessor.vector_attribute(tuple); -// return ev(tuple.m_local_vid); -// } -// case PrimitiveType::Edge: { -// return tuple.m_global_cid; -// } -// case PrimitiveType::Face: -// case PrimitiveType::Tetrahedron: -// default: throw std::runtime_error("Tuple id: Invalid primitive type"); -// } -// } - -// Tuple EdgeMesh::vertex_tuple_from_id(long id) const -// { -// throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); -// ConstAccessor ve_accessor = create_const_accessor(m_ve_handle); -// // confused about this "id", does this mean the id of vertex or the edge? I refer to the -// // TriMesh.cpp(from line 243) -// auto e = ve_accessor.index_access().scalar_attribute(id); -// ConstAccessor ev_accessor = create_const_accessor(m_ev_handle); -// auto ev = ev_accessor.index_access().vector_attribute(e); -// for (long i = 0; i < 2; ++i) { -// if (ev(i) == id) { -// // assert(autogen::auto_2d_table_complete_vertex[i][0] == i); -// // do not know if I use this function right. -// Tuple v_tuple = Tuple( -// i, -// -1, -// -1, -// e, -// get_cell_hash_slow( -// e)); // TODO replace by function that takes hash accessor as parameter -// assert(is_ccw(v_tuple)); // is_ccw also checks for validity -// return v_tuple; -// } -// } -// throw std::runtime_error("vertex_tuple_from_id failed"); -// } - -// Tuple EdgeMesh::edge_tuple_from_id(long id) const -// { -// throw("this function has not been tested! -- EdgeMesh.hpp/EdgeMesh.cpp"); -// Tuple e_tuple = Tuple(-1, -1, -1, id, get_cell_hash_slow(id)); -// assert(is_ccw(e_tuple)); -// assert(is_valid_slow(e_tuple)); -// return e_tuple; -// throw std::runtime_error("edge_tuple_from_id failed"); -// } -// } // namespace wmtk diff --git a/tests/test_tuple_1d.cpp b/tests/test_tuple_1d.cpp index a1dcbd7d87..0d3897eb77 100644 --- a/tests/test_tuple_1d.cpp +++ b/tests/test_tuple_1d.cpp @@ -10,4 +10,143 @@ using namespace wmtk; using namespace wmtk::tests; -TEST_CASE("1D_initialize", "[mesh_creation],[tuple_1d]") {} \ No newline at end of file +TEST_CASE("1D_initialize", "[mesh_creation],[tuple_1d]") +{ + SECTION("init from RowVectors2l") + { + DEBUG_EdgeMesh m; + RowVectors2l lines; + lines.resize(3, 2); + lines << 0, 1, 1, 2, 2, 3; + + m.initialize(lines); + + const std::vector vertices = m.get_all(PrimitiveType::Vertex); + REQUIRE(vertices.size() == 4); + const std::vector edges = m.get_all(PrimitiveType::Edge); + REQUIRE(edges.size() == 3); + + REQUIRE(m.is_connectivity_valid()); + + const Tuple t0 = edges[0]; + const Tuple t1 = edges[1]; + const Tuple t2 = edges[2]; + REQUIRE(m.is_valid_slow(t0)); + REQUIRE(m.is_valid_slow(t1)); + REQUIRE(m.is_valid_slow(t2)); + } + SECTION("init single line") + { + DEBUG_EdgeMesh m = single_line(); + + const std::vector vertices = m.get_all(PrimitiveType::Vertex); + REQUIRE(vertices.size() == 2); + const std::vector edges = m.get_all(PrimitiveType::Edge); + REQUIRE(edges.size() == 1); + + REQUIRE(m.is_connectivity_valid()); + + const Tuple t = edges[0]; + REQUIRE(m.is_valid_slow(t)); + } + SECTION("init multiple lines") + { + DEBUG_EdgeMesh m = multiple_lines(); + + const std::vector vertices = m.get_all(PrimitiveType::Vertex); + REQUIRE(vertices.size() == 6); + const std::vector edges = m.get_all(PrimitiveType::Edge); + REQUIRE(edges.size() == 5); + + REQUIRE(m.is_connectivity_valid()); + + const Tuple t0 = edges[0]; + const Tuple t1 = edges[1]; + const Tuple t2 = edges[2]; + const Tuple t3 = edges[3]; + const Tuple t4 = edges[4]; + REQUIRE(m.is_valid_slow(t0)); + REQUIRE(m.is_valid_slow(t1)); + REQUIRE(m.is_valid_slow(t2)); + REQUIRE(m.is_valid_slow(t3)); + REQUIRE(m.is_valid_slow(t4)); + } + SECTION("init loop lines") + { + DEBUG_EdgeMesh m = loop_lines(); + + const std::vector vertices = m.get_all(PrimitiveType::Vertex); + REQUIRE(vertices.size() == 6); + const std::vector edges = m.get_all(PrimitiveType::Edge); + REQUIRE(edges.size() == 6); + + REQUIRE(m.is_connectivity_valid()); + + const Tuple t0 = edges[0]; + const Tuple t1 = edges[1]; + const Tuple t2 = edges[2]; + const Tuple t3 = edges[3]; + const Tuple t4 = edges[4]; + const Tuple t5 = edges[5]; + REQUIRE(m.is_valid_slow(t0)); + REQUIRE(m.is_valid_slow(t1)); + REQUIRE(m.is_valid_slow(t2)); + REQUIRE(m.is_valid_slow(t3)); + REQUIRE(m.is_valid_slow(t4)); + REQUIRE(m.is_valid_slow(t5)); + } + SECTION("init self loop") + { + DEBUG_EdgeMesh m = self_loop(); + + const std::vector vertices = m.get_all(PrimitiveType::Vertex); + REQUIRE(vertices.size() == 1); + const std::vector edges = m.get_all(PrimitiveType::Edge); + REQUIRE(edges.size() == 1); + + REQUIRE(m.is_connectivity_valid()); + + const Tuple t0 = edges[0]; + REQUIRE(m.is_valid_slow(t0)); + } +} + +TEST_CASE("1D_single_line", "[tuple_generation], [tuple_1d]") +{ + DEBUG_EdgeMesh m = single_line(); + + SECTION("vertices") + { + const std::vector vertices = m.get_all(PrimitiveType::Vertex); + REQUIRE(vertices.size() == 2); + CHECK(m._debug_id(vertices[0], PrimitiveType::Vertex) == 0); + CHECK(m._debug_id(vertices[1], PrimitiveType::Vertex) == 1); + CHECK(m._debug_id(vertices[0], PrimitiveType::Edge) == 0); + CHECK(m._debug_id(vertices[1], PrimitiveType::Edge) == 0); + } + SECTION("edges") + { + const std::vector edges = m.get_all(PrimitiveType::Edge); + REQUIRE(edges.size() == 1); + } +} + +TEST_CASE("1D_single_line", "[tuple_generation], [tuple_1d]") +{ + DEBUG_EdgeMesh m = single_line(); + + SECTION("vertices") + { + const std::vector vertices = m.get_all(PrimitiveType::Vertex); + REQUIRE(vertices.size() == 2); + CHECK(m._debug_id(vertices[0], PrimitiveType::Vertex) == 0); + CHECK(m._debug_id(vertices[1], PrimitiveType::Vertex) == 1); + CHECK(m._debug_id(vertices[0], PrimitiveType::Edge) == 0); + CHECK(m._debug_id(vertices[1], PrimitiveType::Edge) == 0); + } + SECTION("edges") + { + const std::vector edges = m.get_all(PrimitiveType::Edge); + REQUIRE(edges.size() == 1); + } +} \ No newline at end of file From 84436788a69e54ec3bfd8b66ca88ec2760bd2134 Mon Sep 17 00:00:00 2001 From: JcDai Date: Wed, 27 Sep 2023 18:07:11 -0400 Subject: [PATCH 23/49] clean codes --- tests/test_tuple_1d.cpp | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/tests/test_tuple_1d.cpp b/tests/test_tuple_1d.cpp index 0d3897eb77..bc7119f157 100644 --- a/tests/test_tuple_1d.cpp +++ b/tests/test_tuple_1d.cpp @@ -130,23 +130,3 @@ TEST_CASE("1D_single_line", "[tuple_generation], [tuple_1d]") REQUIRE(edges.size() == 1); } } - -TEST_CASE("1D_single_line", "[tuple_generation], [tuple_1d]") -{ - DEBUG_EdgeMesh m = single_line(); - - SECTION("vertices") - { - const std::vector vertices = m.get_all(PrimitiveType::Vertex); - REQUIRE(vertices.size() == 2); - CHECK(m._debug_id(vertices[0], PrimitiveType::Vertex) == 0); - CHECK(m._debug_id(vertices[1], PrimitiveType::Vertex) == 1); - CHECK(m._debug_id(vertices[0], PrimitiveType::Edge) == 0); - CHECK(m._debug_id(vertices[1], PrimitiveType::Edge) == 0); - } - SECTION("edges") - { - const std::vector edges = m.get_all(PrimitiveType::Edge); - REQUIRE(edges.size() == 1); - } -} \ No newline at end of file From 93078edef77a263546e69652965913dcd428166e Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Thu, 28 Sep 2023 11:31:54 -0400 Subject: [PATCH 24/49] fix collapse --- src/wmtk/TriMeshOperationExecutor.cpp | 73 +++++++++++++++++++++++---- src/wmtk/TriMeshOperationExecutor.hpp | 3 ++ 2 files changed, 65 insertions(+), 11 deletions(-) diff --git a/src/wmtk/TriMeshOperationExecutor.cpp b/src/wmtk/TriMeshOperationExecutor.cpp index 38b63c8624..02a1d089d0 100644 --- a/src/wmtk/TriMeshOperationExecutor.cpp +++ b/src/wmtk/TriMeshOperationExecutor.cpp @@ -1,6 +1,6 @@ #include "TriMeshOperationExecutor.hpp" - +#include "SimplicialComplex.hpp" namespace wmtk { TriMesh::TriMeshOperationExecutor::IncidentFaceData @@ -415,7 +415,13 @@ Tuple TriMesh::TriMeshOperationExecutor::split_edge() if (child_new_cell_ids.size() <= i) child_new_cell_ids.emplace_back(-1, -1); continue; } + // BUG FIX HERE: the hash of the cell can be updated during earlier split + // operations auto child_hash_acc = child_tri_mesh.get_cell_hash_accessor(); + long child_cell_hash = + child_hash_acc.index_access().const_scalar_attribute(t_child.m_global_cid); + t_child = t_child.with_updated_hash(child_cell_hash); + TriMesh::TriMeshOperationExecutor executor_child( child_tri_mesh, t_child, @@ -561,8 +567,45 @@ void TriMesh::TriMeshOperationExecutor::update_hash_in_map(TriMesh& child_mesh) } } +bool TriMesh::TriMeshOperationExecutor::can_collapse() const +{ + if (!m_mesh.multi_mesh_manager.is_parent_mesh()) { + return SimplicialComplex::link_cond_bd_2d(m_mesh, m_operating_tuple); + } else { + std::vector> vec_t_child = prepare_operating_tuples_for_child_meshes(); + + for (auto child_mesh_ptr : m_mesh.multi_mesh_manager.child_meshes) { + long child_id = child_mesh_ptr->multi_mesh_manager.child_id(); + + if (child_mesh_ptr->top_simplex_type() == PrimitiveType::Face) { + // this child_mesh is a TriMesh + TriMesh& child_tri_mesh = *std::static_pointer_cast(child_mesh_ptr); + + for (long i = 0; i < long(m_incident_face_datas.size()); ++i) { + Tuple t_child = vec_t_child[i][child_id]; + if (t_child.is_null()) { + continue; + } + if (!SimplicialComplex::link_cond_bd_2d(child_tri_mesh, t_child)) { + return false; + } + } + } + } + + return true; + } +} + +// TODO: possible bugs here, may need do a link_condition check every time before collapse an +// edge_tuple or to generate a link condition that support multiple edges at the same time Tuple TriMesh::TriMeshOperationExecutor::collapse_edge() { + std::cout << "in collapse edge" << std::endl; + if (!can_collapse()) { + std::cout << "cannot collapse at the beginning" << std::endl; + return Tuple(); + } if (!m_mesh.multi_mesh_manager.is_parent_mesh()) { return collapse_edge_single_mesh(); } else { @@ -583,23 +626,31 @@ Tuple TriMesh::TriMeshOperationExecutor::collapse_edge() if (t_child.is_null()) { continue; } + + if (child_tri_mesh.get_flag_accessor(PrimitiveType::Face) + .index_access() + .scalar_attribute(t_child.m_global_cid) == 0) { + std::cout << "the tuple is already deleted in child mesh, skip collapse" + << std::endl; + return Tuple(); + } + + // operations auto child_hash_acc = child_tri_mesh.get_cell_hash_accessor(); - TriMesh::TriMeshOperationExecutor executor_child( - child_tri_mesh, - t_child, - child_hash_acc); - executor_child.collapse_edge(); + long child_cell_hash = + child_hash_acc.index_access().const_scalar_attribute(t_child.m_global_cid); + t_child = t_child.with_updated_hash(child_cell_hash); + + child_tri_mesh.collapse_edge(t_child, child_hash_acc); } - // update_hash update_hash_in_map(child_tri_mesh); } } - + std::cout << "collapse edge done" << std::endl; return ret_tuple; } } - Tuple TriMesh::TriMeshOperationExecutor::collapse_edge_single_mesh() { simplex_ids_to_delete = get_collapse_simplices_to_delete(m_operating_tuple, m_mesh); @@ -650,8 +701,8 @@ Tuple TriMesh::TriMeshOperationExecutor::collapse_edge_single_mesh() return ret; - // return a ccw tuple from left ear if it exists, otherwise return a ccw tuple from right ear - // return m_mesh.tuple_from_id(PrimitiveType::Vertex, v1); + // return a ccw tuple from left ear if it exists, otherwise return a ccw tuple from right + // ear return m_mesh.tuple_from_id(PrimitiveType::Vertex, v1); } std::vector TriMesh::TriMeshOperationExecutor::request_simplex_indices( diff --git a/src/wmtk/TriMeshOperationExecutor.hpp b/src/wmtk/TriMeshOperationExecutor.hpp index da0b2fe376..7be0255966 100644 --- a/src/wmtk/TriMeshOperationExecutor.hpp +++ b/src/wmtk/TriMeshOperationExecutor.hpp @@ -92,6 +92,9 @@ class TriMesh::TriMeshOperationExecutor void connect_ears(); + // check collapse condition on all childmeshes + bool can_collapse() const; + Tuple split_edge(); Tuple collapse_edge(); Tuple split_edge_single_mesh(); From 0191bc1287e6e9cd7d788a01bb0edcd206d16ce0 Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Thu, 28 Sep 2023 13:30:36 -0400 Subject: [PATCH 25/49] add test simplices_to_delete_for_split_1D --- tests/test_1d_operations.cpp | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/tests/test_1d_operations.cpp b/tests/test_1d_operations.cpp index 861d5a13c9..d942b88eae 100644 --- a/tests/test_1d_operations.cpp +++ b/tests/test_1d_operations.cpp @@ -20,10 +20,41 @@ using EMOE = decltype(std::declval().get_emoe( constexpr PrimitiveType PV = PrimitiveType::Vertex; constexpr PrimitiveType PE = PrimitiveType::Edge; -TEST_CASE("edge_mesh", "[operations][1D]") +TEST_CASE("simplices_to_delete_for_split_1D", "[operations][1D]") { SECTION("single line") { - REQUIRE(true); + DEBUG_EdgeMesh m = single_line(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 0; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.split_edge(); + const auto& ids_to_delete = executor.simplex_ids_to_delete; + REQUIRE(ids_to_delete[0].size() == 0); + REQUIRE(ids_to_delete[1].size() == 1); + REQUIRE(ids_to_delete[1][0] == edge_id); + } + + SECTION("self loop") + { + DEBUG_EdgeMesh m = single_line(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 0; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.split_edge(); + const auto& ids_to_delete = executor.simplex_ids_to_delete; + REQUIRE(ids_to_delete[0].size() == 0); + REQUIRE(ids_to_delete[1].size() == 1); + REQUIRE(ids_to_delete[1][0] == edge_id); } } \ No newline at end of file From f9339ea9b83a06dda703cbfd583b5d08874dad34 Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Thu, 28 Sep 2023 14:00:56 -0400 Subject: [PATCH 26/49] add test simplices_to_delete --- src/wmtk/EdgeMesh.cpp | 2 +- src/wmtk/EdgeMeshOperationExecutor.cpp | 4 +-- tests/test_1d_operations.cpp | 45 ++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/wmtk/EdgeMesh.cpp b/src/wmtk/EdgeMesh.cpp index a4177c716e..4b5bd87653 100644 --- a/src/wmtk/EdgeMesh.cpp +++ b/src/wmtk/EdgeMesh.cpp @@ -55,7 +55,7 @@ bool EdgeMesh::is_boundary_vertex(const Tuple& tuple) const { assert(is_valid_slow(tuple)); ConstAccessor ee_accessor = create_const_accessor(m_ee_handle); - return ee_accessor.vector_attribute(tuple)(tuple.m_local_eid) < 0; + return ee_accessor.vector_attribute(tuple)(tuple.m_local_vid) < 0; } Tuple EdgeMesh::switch_tuple(const Tuple& tuple, PrimitiveType type) const diff --git a/src/wmtk/EdgeMeshOperationExecutor.cpp b/src/wmtk/EdgeMeshOperationExecutor.cpp index 7a66833f2a..bda5e267fa 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.cpp +++ b/src/wmtk/EdgeMeshOperationExecutor.cpp @@ -24,11 +24,11 @@ EdgeMesh::EdgeMeshOperationExecutor::EdgeMeshOperationExecutor( // update hash on neighborhood cell_ids_to_update_hash.emplace_back(m_mesh.id_edge(m_operating_tuple)); - if (m_mesh.is_boundary(m_operating_tuple)) { + if (!m_mesh.is_boundary(m_operating_tuple)) { m_neighbor_eids[0] = m_mesh.id_edge(m_mesh.switch_edge(m_operating_tuple)); cell_ids_to_update_hash.emplace_back(m_neighbor_eids[0]); } - if (m_mesh.is_boundary(operating_tuple_switch_vertex)) { + if (!m_mesh.is_boundary(operating_tuple_switch_vertex)) { m_neighbor_eids[1] = m_mesh.id_edge(m_mesh.switch_edge(operating_tuple_switch_vertex)); cell_ids_to_update_hash.emplace_back(m_neighbor_eids[1]); } diff --git a/tests/test_1d_operations.cpp b/tests/test_1d_operations.cpp index d942b88eae..d30136a96c 100644 --- a/tests/test_1d_operations.cpp +++ b/tests/test_1d_operations.cpp @@ -42,7 +42,7 @@ TEST_CASE("simplices_to_delete_for_split_1D", "[operations][1D]") SECTION("self loop") { - DEBUG_EdgeMesh m = single_line(); + DEBUG_EdgeMesh m = self_loop(); REQUIRE(m.is_connectivity_valid()); const long edge_id = 0; @@ -57,4 +57,45 @@ TEST_CASE("simplices_to_delete_for_split_1D", "[operations][1D]") REQUIRE(ids_to_delete[1].size() == 1); REQUIRE(ids_to_delete[1][0] == edge_id); } -} \ No newline at end of file +} + +TEST_CASE("simplices_to_delete_for_collapse_1D", "[operations][1D]") +{ + SECTION("multiple_lines") + { + DEBUG_EdgeMesh m = multiple_lines(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 2; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.collapse_edge(); + const auto& ids_to_delete = executor.simplex_ids_to_delete; + REQUIRE(ids_to_delete[0].size() == 1); + REQUIRE(ids_to_delete[0][0] == 3); + REQUIRE(ids_to_delete[1].size() == 1); + REQUIRE(ids_to_delete[1][0] == edge_id); + } + + SECTION("two_line_loop") + { + DEBUG_EdgeMesh m = two_line_loop(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 0; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.collapse_edge(); + const auto& ids_to_delete = executor.simplex_ids_to_delete; + REQUIRE(ids_to_delete[0].size() == 1); + REQUIRE(ids_to_delete[0][0] == 1); + REQUIRE(ids_to_delete[1].size() == 1); + REQUIRE(ids_to_delete[1][0] == edge_id); + } +} From e68073438fa056d865abd9a0567ec2c2b246ab82 Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Thu, 28 Sep 2023 14:30:08 -0400 Subject: [PATCH 27/49] add split and collapse test, need fix collapse --- tests/test_1d_operations.cpp | 190 +++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) diff --git a/tests/test_1d_operations.cpp b/tests/test_1d_operations.cpp index d30136a96c..d67173f337 100644 --- a/tests/test_1d_operations.cpp +++ b/tests/test_1d_operations.cpp @@ -34,6 +34,7 @@ TEST_CASE("simplices_to_delete_for_split_1D", "[operations][1D]") auto executor = m.get_emoe(edge, hash_accessor); executor.split_edge(); + REQUIRE(m.is_connectivity_valid()); const auto& ids_to_delete = executor.simplex_ids_to_delete; REQUIRE(ids_to_delete[0].size() == 0); REQUIRE(ids_to_delete[1].size() == 1); @@ -52,6 +53,7 @@ TEST_CASE("simplices_to_delete_for_split_1D", "[operations][1D]") auto executor = m.get_emoe(edge, hash_accessor); executor.split_edge(); + REQUIRE(m.is_connectivity_valid()); const auto& ids_to_delete = executor.simplex_ids_to_delete; REQUIRE(ids_to_delete[0].size() == 0); REQUIRE(ids_to_delete[1].size() == 1); @@ -73,6 +75,7 @@ TEST_CASE("simplices_to_delete_for_collapse_1D", "[operations][1D]") auto executor = m.get_emoe(edge, hash_accessor); executor.collapse_edge(); + REQUIRE(m.is_connectivity_valid()); const auto& ids_to_delete = executor.simplex_ids_to_delete; REQUIRE(ids_to_delete[0].size() == 1); REQUIRE(ids_to_delete[0][0] == 3); @@ -99,3 +102,190 @@ TEST_CASE("simplices_to_delete_for_collapse_1D", "[operations][1D]") REQUIRE(ids_to_delete[1][0] == edge_id); } } + + +TEST_CASE("collapse_edge_1D", "[operations][1D]") +{ + SECTION("multiple_lines") + { + DEBUG_EdgeMesh m = multiple_lines(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 2; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.collapse_edge(); + CHECK(m.is_connectivity_valid()); + } + + SECTION("single_line") + { + DEBUG_EdgeMesh m = single_line(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 0; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.collapse_edge(); + CHECK(m.is_connectivity_valid()); + } + + SECTION("self_loop") + { + DEBUG_EdgeMesh m = self_loop(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 0; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.collapse_edge(); + CHECK(m.is_connectivity_valid()); + } + + SECTION("two_line_loop") + { + DEBUG_EdgeMesh m = two_line_loop(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 0; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.collapse_edge(); + CHECK(m.is_connectivity_valid()); + } + + SECTION("self_loop") + { + DEBUG_EdgeMesh m = self_loop(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 0; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.collapse_edge(); + CHECK(m.is_connectivity_valid()); + } + + SECTION("loop_lines") + { + DEBUG_EdgeMesh m = loop_lines(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 0; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.collapse_edge(); + CHECK(m.is_connectivity_valid()); + } +} + +TEST_CASE("split_edge_1D", "[operations][1D]") +{ + SECTION("multiple_lines") + { + DEBUG_EdgeMesh m = multiple_lines(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 2; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.split_edge(); + CHECK(m.is_connectivity_valid()); + } + + SECTION("single_line") + { + DEBUG_EdgeMesh m = single_line(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 0; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.split_edge(); + CHECK(m.is_connectivity_valid()); + } + + SECTION("self_loop") + { + DEBUG_EdgeMesh m = self_loop(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 0; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.split_edge(); + CHECK(m.is_connectivity_valid()); + } + + SECTION("two_line_loop") + { + DEBUG_EdgeMesh m = two_line_loop(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 0; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.split_edge(); + CHECK(m.is_connectivity_valid()); + } + + SECTION("self_loop") + { + DEBUG_EdgeMesh m = self_loop(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 0; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.split_edge(); + CHECK(m.is_connectivity_valid()); + } + + SECTION("loop_lines") + { + DEBUG_EdgeMesh m = loop_lines(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 0; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.split_edge(); + CHECK(m.is_connectivity_valid()); + } +} \ No newline at end of file From 36f5b4b724fc7cbf763bf19dec62fb7672e73133 Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Thu, 28 Sep 2023 14:54:33 -0400 Subject: [PATCH 28/49] fix ccw, still need fix collapse --- src/wmtk/EdgeMesh.cpp | 4 +- src/wmtk/EdgeMeshOperationExecutor.cpp | 20 ++++ tests/test_1d_operations.cpp | 152 ++++++++++++------------- 3 files changed, 98 insertions(+), 78 deletions(-) diff --git a/src/wmtk/EdgeMesh.cpp b/src/wmtk/EdgeMesh.cpp index 4b5bd87653..1b30d0787e 100644 --- a/src/wmtk/EdgeMesh.cpp +++ b/src/wmtk/EdgeMesh.cpp @@ -110,7 +110,7 @@ Tuple EdgeMesh::switch_tuple(const Tuple& tuple, PrimitiveType type) const bool EdgeMesh::is_ccw(const Tuple& tuple) const { assert(is_valid_slow(tuple)); - return tuple.m_local_vid == 1; + return tuple.m_local_vid == 0; } void EdgeMesh::initialize( @@ -197,7 +197,7 @@ Tuple EdgeMesh::vertex_tuple_from_id(long id) const Tuple EdgeMesh::edge_tuple_from_id(long id) const { - Tuple e_tuple = Tuple(1, -1, -1, id, get_cell_hash_slow(id)); + Tuple e_tuple = Tuple(0, -1, -1, id, get_cell_hash_slow(id)); assert(is_valid_slow(e_tuple)); return e_tuple; diff --git a/src/wmtk/EdgeMeshOperationExecutor.cpp b/src/wmtk/EdgeMeshOperationExecutor.cpp index bda5e267fa..433a9fa5ca 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.cpp +++ b/src/wmtk/EdgeMeshOperationExecutor.cpp @@ -195,6 +195,16 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge_single_mesh() } } + // TODO: for debug + for (long i = 0; i < 2; i++) { + if (m_neighbor_eids[i] != -1) { + auto ee_neighbor = ee_accessor.index_access().vector_attribute(m_neighbor_eids[i]); + std::cout << "m_neighbor_eid " << m_neighbor_eids[i] << ": " << m_neighbor_eids[i] + << std::endl; + std::cout << ee_neighbor(0) << " " << ee_neighbor(1) << std::endl; + } + } + // update ev { if (m_neighbor_eids[1] != -1) { @@ -207,6 +217,16 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge_single_mesh() } } + // TODO: for debug + for (long i = 0; i < 2; i++) { + if (m_neighbor_eids[i] != -1) { + auto ee_neighbor = ee_accessor.index_access().vector_attribute(m_neighbor_eids[i]); + std::cout << "m_neighbor_eid " << m_neighbor_eids[i] << ": " << m_neighbor_eids[i] + << std::endl; + std::cout << ee_neighbor(0) << " " << ee_neighbor(1) << std::endl; + } + } + // update ve { ve_accessor.index_access().scalar_attribute(m_spine_vids[0]) = m_neighbor_eids[1]; diff --git a/tests/test_1d_operations.cpp b/tests/test_1d_operations.cpp index d67173f337..f1c2be394c 100644 --- a/tests/test_1d_operations.cpp +++ b/tests/test_1d_operations.cpp @@ -75,10 +75,10 @@ TEST_CASE("simplices_to_delete_for_collapse_1D", "[operations][1D]") auto executor = m.get_emoe(edge, hash_accessor); executor.collapse_edge(); - REQUIRE(m.is_connectivity_valid()); + // REQUIRE(m.is_connectivity_valid()); const auto& ids_to_delete = executor.simplex_ids_to_delete; REQUIRE(ids_to_delete[0].size() == 1); - REQUIRE(ids_to_delete[0][0] == 3); + REQUIRE(ids_to_delete[0][0] == 2); REQUIRE(ids_to_delete[1].size() == 1); REQUIRE(ids_to_delete[1][0] == edge_id); } @@ -97,7 +97,7 @@ TEST_CASE("simplices_to_delete_for_collapse_1D", "[operations][1D]") executor.collapse_edge(); const auto& ids_to_delete = executor.simplex_ids_to_delete; REQUIRE(ids_to_delete[0].size() == 1); - REQUIRE(ids_to_delete[0][0] == 1); + REQUIRE(ids_to_delete[0][0] == 0); REQUIRE(ids_to_delete[1].size() == 1); REQUIRE(ids_to_delete[1][0] == edge_id); } @@ -106,50 +106,50 @@ TEST_CASE("simplices_to_delete_for_collapse_1D", "[operations][1D]") TEST_CASE("collapse_edge_1D", "[operations][1D]") { - SECTION("multiple_lines") - { - DEBUG_EdgeMesh m = multiple_lines(); - REQUIRE(m.is_connectivity_valid()); - - const long edge_id = 2; - Tuple edge = m.tuple_from_edge_id(edge_id); - REQUIRE(m.is_valid_slow(edge)); - Accessor hash_accessor = m.get_cell_hash_accessor(); - auto executor = m.get_emoe(edge, hash_accessor); - - executor.collapse_edge(); - CHECK(m.is_connectivity_valid()); - } - - SECTION("single_line") - { - DEBUG_EdgeMesh m = single_line(); - REQUIRE(m.is_connectivity_valid()); - - const long edge_id = 0; - Tuple edge = m.tuple_from_edge_id(edge_id); - REQUIRE(m.is_valid_slow(edge)); - Accessor hash_accessor = m.get_cell_hash_accessor(); - auto executor = m.get_emoe(edge, hash_accessor); - - executor.collapse_edge(); - CHECK(m.is_connectivity_valid()); - } - - SECTION("self_loop") - { - DEBUG_EdgeMesh m = self_loop(); - REQUIRE(m.is_connectivity_valid()); - - const long edge_id = 0; - Tuple edge = m.tuple_from_edge_id(edge_id); - REQUIRE(m.is_valid_slow(edge)); - Accessor hash_accessor = m.get_cell_hash_accessor(); - auto executor = m.get_emoe(edge, hash_accessor); - - executor.collapse_edge(); - CHECK(m.is_connectivity_valid()); - } + // SECTION("multiple_lines") + // { + // DEBUG_EdgeMesh m = multiple_lines(); + // REQUIRE(m.is_connectivity_valid()); + + // const long edge_id = 2; + // Tuple edge = m.tuple_from_edge_id(edge_id); + // REQUIRE(m.is_valid_slow(edge)); + // Accessor hash_accessor = m.get_cell_hash_accessor(); + // auto executor = m.get_emoe(edge, hash_accessor); + + // executor.collapse_edge(); + // CHECK(m.is_connectivity_valid()); + // } + + // SECTION("single_line") + // { + // DEBUG_EdgeMesh m = single_line(); + // REQUIRE(m.is_connectivity_valid()); + + // const long edge_id = 0; + // Tuple edge = m.tuple_from_edge_id(edge_id); + // REQUIRE(m.is_valid_slow(edge)); + // Accessor hash_accessor = m.get_cell_hash_accessor(); + // auto executor = m.get_emoe(edge, hash_accessor); + + // executor.collapse_edge(); + // CHECK(m.is_connectivity_valid()); + // } + + // SECTION("self_loop") + // { + // DEBUG_EdgeMesh m = self_loop(); + // REQUIRE(m.is_connectivity_valid()); + + // const long edge_id = 0; + // Tuple edge = m.tuple_from_edge_id(edge_id); + // REQUIRE(m.is_valid_slow(edge)); + // Accessor hash_accessor = m.get_cell_hash_accessor(); + // auto executor = m.get_emoe(edge, hash_accessor); + + // executor.collapse_edge(); + // CHECK(m.is_connectivity_valid()); + // } SECTION("two_line_loop") { @@ -166,35 +166,35 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") CHECK(m.is_connectivity_valid()); } - SECTION("self_loop") - { - DEBUG_EdgeMesh m = self_loop(); - REQUIRE(m.is_connectivity_valid()); - - const long edge_id = 0; - Tuple edge = m.tuple_from_edge_id(edge_id); - REQUIRE(m.is_valid_slow(edge)); - Accessor hash_accessor = m.get_cell_hash_accessor(); - auto executor = m.get_emoe(edge, hash_accessor); - - executor.collapse_edge(); - CHECK(m.is_connectivity_valid()); - } - - SECTION("loop_lines") - { - DEBUG_EdgeMesh m = loop_lines(); - REQUIRE(m.is_connectivity_valid()); - - const long edge_id = 0; - Tuple edge = m.tuple_from_edge_id(edge_id); - REQUIRE(m.is_valid_slow(edge)); - Accessor hash_accessor = m.get_cell_hash_accessor(); - auto executor = m.get_emoe(edge, hash_accessor); - - executor.collapse_edge(); - CHECK(m.is_connectivity_valid()); - } + // SECTION("self_loop") + // { + // DEBUG_EdgeMesh m = self_loop(); + // REQUIRE(m.is_connectivity_valid()); + + // const long edge_id = 0; + // Tuple edge = m.tuple_from_edge_id(edge_id); + // REQUIRE(m.is_valid_slow(edge)); + // Accessor hash_accessor = m.get_cell_hash_accessor(); + // auto executor = m.get_emoe(edge, hash_accessor); + + // executor.collapse_edge(); + // CHECK(m.is_connectivity_valid()); + // } + + // SECTION("loop_lines") + // { + // DEBUG_EdgeMesh m = loop_lines(); + // REQUIRE(m.is_connectivity_valid()); + + // const long edge_id = 0; + // Tuple edge = m.tuple_from_edge_id(edge_id); + // REQUIRE(m.is_valid_slow(edge)); + // Accessor hash_accessor = m.get_cell_hash_accessor(); + // auto executor = m.get_emoe(edge, hash_accessor); + + // executor.collapse_edge(); + // CHECK(m.is_connectivity_valid()); + // } } TEST_CASE("split_edge_1D", "[operations][1D]") From d5ae116b452cee0593c57e651406298aace027bd Mon Sep 17 00:00:00 2001 From: JcDai Date: Thu, 28 Sep 2023 14:55:02 -0400 Subject: [PATCH 29/49] add more 1d topology test --- tests/test_topology.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/test_topology.cpp b/tests/test_topology.cpp index 3bd26af6b6..e490e77c81 100644 --- a/tests/test_topology.cpp +++ b/tests/test_topology.cpp @@ -416,6 +416,37 @@ TEST_CASE("topology_of_loop", "[topology][1D]") CHECK((E.row(VE(i)).array() == i).any()); } + // 2. Test relationship between EV and EE + for (int i = 0; i < EE.rows(); ++i) { + for (int j = 0; j < 2; ++j) { + long nb = EE(i, j); + if (nb < 0) continue; + + CHECK((EE.row(nb).array() == i).any()); + + // TODO add checks + } + } +} + +TEST_CASE("topology_of_two_line_loop", "[topology][1D]") +{ + /* + 0 -- 1 -- 0* + */ + Eigen::Matrix E; + E << 0, 1, 1, 0; + auto [EE, VE] = edgemesh_topology_initialization(E); + + std::cout << "EV:\n" << E << std::endl; + std::cout << "EE:\n" << EE << std::endl; + std::cout << "VE:\n" << VE << std::endl; + + // 1. Test relationship between VE and EV + for (int i = 0; i < VE.size(); ++i) { + CHECK((E.row(VE(i)).array() == i).any()); + } + // 2. Test relationship between EV and EE for (int i = 0; i < EE.rows(); ++i) { for (int j = 0; j < 2; ++j) { From 436714d4b3c01c17065c6c0ecbbb8fab0c9404a6 Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Thu, 28 Sep 2023 14:57:26 -0400 Subject: [PATCH 30/49] fix collapse, seems to be correct --- src/wmtk/EdgeMeshOperationExecutor.cpp | 24 +--- tests/test_1d_operations.cpp | 146 ++++++++++++------------- 2 files changed, 75 insertions(+), 95 deletions(-) diff --git a/src/wmtk/EdgeMeshOperationExecutor.cpp b/src/wmtk/EdgeMeshOperationExecutor.cpp index 433a9fa5ca..1df3345771 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.cpp +++ b/src/wmtk/EdgeMeshOperationExecutor.cpp @@ -195,38 +195,18 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge_single_mesh() } } - // TODO: for debug - for (long i = 0; i < 2; i++) { - if (m_neighbor_eids[i] != -1) { - auto ee_neighbor = ee_accessor.index_access().vector_attribute(m_neighbor_eids[i]); - std::cout << "m_neighbor_eid " << m_neighbor_eids[i] << ": " << m_neighbor_eids[i] - << std::endl; - std::cout << ee_neighbor(0) << " " << ee_neighbor(1) << std::endl; - } - } - // update ev { if (m_neighbor_eids[1] != -1) { auto ev_neighbor = ev_accessor.index_access().vector_attribute(m_neighbor_eids[1]); for (long j = 0; j < 2; j++) { - if (ev_neighbor[j] == m_spine_vids[1]) { - ev_neighbor[j] = m_spine_vids[0]; + if (ev_neighbor[j] == m_spine_vids[0]) { + ev_neighbor[j] = m_spine_vids[1]; } } } } - // TODO: for debug - for (long i = 0; i < 2; i++) { - if (m_neighbor_eids[i] != -1) { - auto ee_neighbor = ee_accessor.index_access().vector_attribute(m_neighbor_eids[i]); - std::cout << "m_neighbor_eid " << m_neighbor_eids[i] << ": " << m_neighbor_eids[i] - << std::endl; - std::cout << ee_neighbor(0) << " " << ee_neighbor(1) << std::endl; - } - } - // update ve { ve_accessor.index_access().scalar_attribute(m_spine_vids[0]) = m_neighbor_eids[1]; diff --git a/tests/test_1d_operations.cpp b/tests/test_1d_operations.cpp index f1c2be394c..3ca321c646 100644 --- a/tests/test_1d_operations.cpp +++ b/tests/test_1d_operations.cpp @@ -106,50 +106,50 @@ TEST_CASE("simplices_to_delete_for_collapse_1D", "[operations][1D]") TEST_CASE("collapse_edge_1D", "[operations][1D]") { - // SECTION("multiple_lines") - // { - // DEBUG_EdgeMesh m = multiple_lines(); - // REQUIRE(m.is_connectivity_valid()); - - // const long edge_id = 2; - // Tuple edge = m.tuple_from_edge_id(edge_id); - // REQUIRE(m.is_valid_slow(edge)); - // Accessor hash_accessor = m.get_cell_hash_accessor(); - // auto executor = m.get_emoe(edge, hash_accessor); - - // executor.collapse_edge(); - // CHECK(m.is_connectivity_valid()); - // } - - // SECTION("single_line") - // { - // DEBUG_EdgeMesh m = single_line(); - // REQUIRE(m.is_connectivity_valid()); - - // const long edge_id = 0; - // Tuple edge = m.tuple_from_edge_id(edge_id); - // REQUIRE(m.is_valid_slow(edge)); - // Accessor hash_accessor = m.get_cell_hash_accessor(); - // auto executor = m.get_emoe(edge, hash_accessor); - - // executor.collapse_edge(); - // CHECK(m.is_connectivity_valid()); - // } - - // SECTION("self_loop") - // { - // DEBUG_EdgeMesh m = self_loop(); - // REQUIRE(m.is_connectivity_valid()); - - // const long edge_id = 0; - // Tuple edge = m.tuple_from_edge_id(edge_id); - // REQUIRE(m.is_valid_slow(edge)); - // Accessor hash_accessor = m.get_cell_hash_accessor(); - // auto executor = m.get_emoe(edge, hash_accessor); - - // executor.collapse_edge(); - // CHECK(m.is_connectivity_valid()); - // } + SECTION("multiple_lines") + { + DEBUG_EdgeMesh m = multiple_lines(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 2; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.collapse_edge(); + CHECK(m.is_connectivity_valid()); + } + + SECTION("single_line") + { + DEBUG_EdgeMesh m = single_line(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 0; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.collapse_edge(); + CHECK(m.is_connectivity_valid()); + } + + SECTION("self_loop") + { + DEBUG_EdgeMesh m = self_loop(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 0; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.collapse_edge(); + CHECK(m.is_connectivity_valid()); + } SECTION("two_line_loop") { @@ -166,35 +166,35 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") CHECK(m.is_connectivity_valid()); } - // SECTION("self_loop") - // { - // DEBUG_EdgeMesh m = self_loop(); - // REQUIRE(m.is_connectivity_valid()); - - // const long edge_id = 0; - // Tuple edge = m.tuple_from_edge_id(edge_id); - // REQUIRE(m.is_valid_slow(edge)); - // Accessor hash_accessor = m.get_cell_hash_accessor(); - // auto executor = m.get_emoe(edge, hash_accessor); - - // executor.collapse_edge(); - // CHECK(m.is_connectivity_valid()); - // } - - // SECTION("loop_lines") - // { - // DEBUG_EdgeMesh m = loop_lines(); - // REQUIRE(m.is_connectivity_valid()); - - // const long edge_id = 0; - // Tuple edge = m.tuple_from_edge_id(edge_id); - // REQUIRE(m.is_valid_slow(edge)); - // Accessor hash_accessor = m.get_cell_hash_accessor(); - // auto executor = m.get_emoe(edge, hash_accessor); - - // executor.collapse_edge(); - // CHECK(m.is_connectivity_valid()); - // } + SECTION("self_loop") + { + DEBUG_EdgeMesh m = self_loop(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 0; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.collapse_edge(); + CHECK(m.is_connectivity_valid()); + } + + SECTION("loop_lines") + { + DEBUG_EdgeMesh m = loop_lines(); + REQUIRE(m.is_connectivity_valid()); + + const long edge_id = 0; + Tuple edge = m.tuple_from_edge_id(edge_id); + REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + auto executor = m.get_emoe(edge, hash_accessor); + + executor.collapse_edge(); + CHECK(m.is_connectivity_valid()); + } } TEST_CASE("split_edge_1D", "[operations][1D]") From d3fd97891844ae191a2a5a890f9c8088d32377af Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Thu, 28 Sep 2023 16:22:51 -0400 Subject: [PATCH 31/49] add is_simplex_deleted function in DEBUG_EdgeMesh --- src/wmtk/EdgeMeshOperationExecutor.cpp | 6 +++- src/wmtk/attribute/ConstAccessor.hpp | 7 ++++ tests/test_1d_operations.cpp | 47 +++++++++++++++----------- tests/tools/DEBUG_EdgeMesh.cpp | 6 ++++ tests/tools/DEBUG_EdgeMesh.hpp | 2 ++ 5 files changed, 47 insertions(+), 21 deletions(-) diff --git a/src/wmtk/EdgeMeshOperationExecutor.cpp b/src/wmtk/EdgeMeshOperationExecutor.cpp index 1df3345771..d22ea5073b 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.cpp +++ b/src/wmtk/EdgeMeshOperationExecutor.cpp @@ -216,7 +216,11 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge_single_mesh() delete_simplices(); const long ret_eid = m_neighbor_eids[0] == -1 ? m_neighbor_eids[1] : m_neighbor_eids[0]; - return m_mesh.edge_tuple_from_id(ret_eid); + Tuple ret_tuple = m_mesh.edge_tuple_from_id(ret_eid); + if (m_mesh.id_vertex(ret_tuple) != m_spine_vids[1]) { + ret_tuple = m_mesh.switch_vertex(ret_tuple); + } + return ret_tuple; } std::vector EdgeMesh::EdgeMeshOperationExecutor::request_simplex_indices( diff --git a/src/wmtk/attribute/ConstAccessor.hpp b/src/wmtk/attribute/ConstAccessor.hpp index 752e87d5ae..fdac496c10 100644 --- a/src/wmtk/attribute/ConstAccessor.hpp +++ b/src/wmtk/attribute/ConstAccessor.hpp @@ -7,6 +7,11 @@ class Mesh; class TriMesh; class TetMesh; class TriMeshOperationExecutor; +class EdgeMesh; +namespace tests { +class DEBUG_TriMesh; +class DEBUG_EdgeMesh; +} // namespace tests } // namespace wmtk namespace wmtk::attribute { @@ -21,6 +26,8 @@ class ConstAccessor : protected TupleAccessor friend class wmtk::EdgeMesh; friend class wmtk::PointMesh; friend class wmtk::TriMeshOperationExecutor; + friend class wmtk::tests::DEBUG_TriMesh; + friend class wmtk::tests::DEBUG_EdgeMesh; using Scalar = T; friend class AttributeCache; diff --git a/tests/test_1d_operations.cpp b/tests/test_1d_operations.cpp index 3ca321c646..5ce42ed0d2 100644 --- a/tests/test_1d_operations.cpp +++ b/tests/test_1d_operations.cpp @@ -114,11 +114,25 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") const long edge_id = 2; Tuple edge = m.tuple_from_edge_id(edge_id); REQUIRE(m.is_valid_slow(edge)); + const long vertex_id = m._debug_id(edge, PV); + std::cout << "edge_id = " << edge_id << "\t vertex_id = " << vertex_id << std::endl; + Accessor hash_accessor = m.get_cell_hash_accessor(); auto executor = m.get_emoe(edge, hash_accessor); - - executor.collapse_edge(); CHECK(m.is_connectivity_valid()); + + const Tuple ret_tuple = executor.collapse_edge(); + CHECK(!ret_tuple.is_null()); // collapse operation is valid + // check return tuple + CHECK(m._debug_id(ret_tuple, PE) == 1); + CHECK(m._debug_id(ret_tuple, PV) == 3); + // check delete + CHECK(m.is_simplex_deleted(PE, edge_id)); + CHECK(m.is_simplex_deleted(PV, vertex_id)); + + const auto ve = m.create_base_accessor(m.ve_handle()); + const auto ee = m.create_base_accessor(m.e_handle(PE)); + const auto ev = m.create_base_accessor(m.e_handle(PV)); } SECTION("single_line") @@ -132,7 +146,8 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") Accessor hash_accessor = m.get_cell_hash_accessor(); auto executor = m.get_emoe(edge, hash_accessor); - executor.collapse_edge(); + const Tuple ret_tuple = executor.collapse_edge(); + CHECK(ret_tuple.is_null()); // collapse opearation is invalid CHECK(m.is_connectivity_valid()); } @@ -147,7 +162,8 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") Accessor hash_accessor = m.get_cell_hash_accessor(); auto executor = m.get_emoe(edge, hash_accessor); - executor.collapse_edge(); + const Tuple ret_tuple = executor.collapse_edge(); + CHECK(ret_tuple.is_null()); // collapse opearation is invalid CHECK(m.is_connectivity_valid()); } @@ -162,22 +178,10 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") Accessor hash_accessor = m.get_cell_hash_accessor(); auto executor = m.get_emoe(edge, hash_accessor); - executor.collapse_edge(); - CHECK(m.is_connectivity_valid()); - } + const Tuple ret_tuple = executor.collapse_edge(); + CHECK(!ret_tuple.is_null()); // collapse operation is valid + // check return tuple - SECTION("self_loop") - { - DEBUG_EdgeMesh m = self_loop(); - REQUIRE(m.is_connectivity_valid()); - - const long edge_id = 0; - Tuple edge = m.tuple_from_edge_id(edge_id); - REQUIRE(m.is_valid_slow(edge)); - Accessor hash_accessor = m.get_cell_hash_accessor(); - auto executor = m.get_emoe(edge, hash_accessor); - - executor.collapse_edge(); CHECK(m.is_connectivity_valid()); } @@ -192,7 +196,10 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") Accessor hash_accessor = m.get_cell_hash_accessor(); auto executor = m.get_emoe(edge, hash_accessor); - executor.collapse_edge(); + const Tuple ret_tuple = executor.collapse_edge(); + CHECK(!ret_tuple.is_null()); // collapse operation is valid + // check return tuple + CHECK(m.is_connectivity_valid()); } } diff --git a/tests/tools/DEBUG_EdgeMesh.cpp b/tests/tools/DEBUG_EdgeMesh.cpp index def5315aa1..598767d0f2 100644 --- a/tests/tools/DEBUG_EdgeMesh.cpp +++ b/tests/tools/DEBUG_EdgeMesh.cpp @@ -118,4 +118,10 @@ auto DEBUG_EdgeMesh::get_emoe(const Tuple& t, Accessor& hash_accessor) { return EdgeMeshOperationExecutor(*this, t, hash_accessor); } + +bool DEBUG_EdgeMesh::is_simplex_deleted(PrimitiveType type, const long id) const +{ + const auto flag_accessor = get_flag_accessor(type); + return flag_accessor.index_access().scalar_attribute(id) == 0; +} } // namespace wmtk::tests diff --git a/tests/tools/DEBUG_EdgeMesh.hpp b/tests/tools/DEBUG_EdgeMesh.hpp index 3f2300d0b4..9d7be7fa1f 100644 --- a/tests/tools/DEBUG_EdgeMesh.hpp +++ b/tests/tools/DEBUG_EdgeMesh.hpp @@ -62,6 +62,8 @@ class DEBUG_EdgeMesh : public EdgeMesh Accessor get_cell_hash_accessor(); EdgeMeshOperationExecutor get_emoe(const Tuple& t, Accessor& hash_accessor); + + bool is_simplex_deleted(PrimitiveType type, const long id) const; }; } // namespace wmtk::tests From 8163b71dacf7a1a0850521225284c2083e79fe6d Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Thu, 28 Sep 2023 16:39:01 -0400 Subject: [PATCH 32/49] fix collapse edge ev update --- src/wmtk/EdgeMeshOperationExecutor.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/wmtk/EdgeMeshOperationExecutor.cpp b/src/wmtk/EdgeMeshOperationExecutor.cpp index d22ea5073b..f92c3983c5 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.cpp +++ b/src/wmtk/EdgeMeshOperationExecutor.cpp @@ -197,8 +197,8 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge_single_mesh() // update ev { - if (m_neighbor_eids[1] != -1) { - auto ev_neighbor = ev_accessor.index_access().vector_attribute(m_neighbor_eids[1]); + if (m_neighbor_eids[0] != -1) { + auto ev_neighbor = ev_accessor.index_access().vector_attribute(m_neighbor_eids[0]); for (long j = 0; j < 2; j++) { if (ev_neighbor[j] == m_spine_vids[0]) { ev_neighbor[j] = m_spine_vids[1]; @@ -207,6 +207,7 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge_single_mesh() } } + // update ve { ve_accessor.index_access().scalar_attribute(m_spine_vids[0]) = m_neighbor_eids[1]; @@ -217,6 +218,7 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge_single_mesh() const long ret_eid = m_neighbor_eids[0] == -1 ? m_neighbor_eids[1] : m_neighbor_eids[0]; Tuple ret_tuple = m_mesh.edge_tuple_from_id(ret_eid); + if (m_mesh.id_vertex(ret_tuple) != m_spine_vids[1]) { ret_tuple = m_mesh.switch_vertex(ret_tuple); } From 36ef0f28a3dd2bc75d87646e6908609cb50bff38 Mon Sep 17 00:00:00 2001 From: JcDai Date: Thu, 28 Sep 2023 16:40:16 -0400 Subject: [PATCH 33/49] fix bug for self loop otopo init --- src/wmtk/EdgeMesh.cpp | 1 + .../edgemesh_topology_initialization.cpp | 3 +- tests/test_topology.cpp | 31 +++ tests/test_tuple_1d.cpp | 236 ++++++++++++++++++ 4 files changed, 270 insertions(+), 1 deletion(-) diff --git a/src/wmtk/EdgeMesh.cpp b/src/wmtk/EdgeMesh.cpp index 1b30d0787e..f4b50f4f9c 100644 --- a/src/wmtk/EdgeMesh.cpp +++ b/src/wmtk/EdgeMesh.cpp @@ -86,6 +86,7 @@ Tuple EdgeMesh::switch_tuple(const Tuple& tuple, PrimitiveType type) const for (long i = 0; i < 2; ++i) { if (ev(i) == gvid) { lvid_new = i; + // break; } } assert(lvid_new != -1); diff --git a/src/wmtk/utils/edgemesh_topology_initialization.cpp b/src/wmtk/utils/edgemesh_topology_initialization.cpp index d4636becc0..5fa8bd98cf 100644 --- a/src/wmtk/utils/edgemesh_topology_initialization.cpp +++ b/src/wmtk/utils/edgemesh_topology_initialization.cpp @@ -41,7 +41,8 @@ std::tuple edgemesh_topology_initialization( for (int k = 0; k < 2; ++k) { if (E(complete_VE[i][k], 0) == i) { EE(complete_VE[i][k], 0) = complete_VE[i][1 - k]; - } else { + } + if (E(complete_VE[i][k], 1) == i) { EE(complete_VE[i][k], 1) = complete_VE[i][1 - k]; } } diff --git a/tests/test_topology.cpp b/tests/test_topology.cpp index e490e77c81..0dcfaf5e8f 100644 --- a/tests/test_topology.cpp +++ b/tests/test_topology.cpp @@ -447,6 +447,37 @@ TEST_CASE("topology_of_two_line_loop", "[topology][1D]") CHECK((E.row(VE(i)).array() == i).any()); } + // 2. Test relationship between EV and EE + for (int i = 0; i < EE.rows(); ++i) { + for (int j = 0; j < 2; ++j) { + long nb = EE(i, j); + if (nb < 0) continue; + + CHECK((EE.row(nb).array() == i).any()); + + // TODO add checks + } + } +} + +TEST_CASE("topology_of_self_loop", "[topology][1D]") +{ + /* + 0 -- 0* + */ + Eigen::Matrix E; + E << 0, 0; + auto [EE, VE] = edgemesh_topology_initialization(E); + + std::cout << "EV:\n" << E << std::endl; + std::cout << "EE:\n" << EE << std::endl; + std::cout << "VE:\n" << VE << std::endl; + + // 1. Test relationship between VE and EV + for (int i = 0; i < VE.size(); ++i) { + CHECK((E.row(VE(i)).array() == i).any()); + } + // 2. Test relationship between EV and EE for (int i = 0; i < EE.rows(); ++i) { for (int j = 0; j < 2; ++j) { diff --git a/tests/test_tuple_1d.cpp b/tests/test_tuple_1d.cpp index bc7119f157..e4ba68d871 100644 --- a/tests/test_tuple_1d.cpp +++ b/tests/test_tuple_1d.cpp @@ -130,3 +130,239 @@ TEST_CASE("1D_single_line", "[tuple_generation], [tuple_1d]") REQUIRE(edges.size() == 1); } } + +TEST_CASE("1D_multiple_lines", "[tuple_generation], [tuple_1d]") +{ + DEBUG_EdgeMesh m = multiple_lines(); + + SECTION("vertices") + { + const std::vector vertices = m.get_all(PrimitiveType::Vertex); + REQUIRE(vertices.size() == 6); + CHECK(m._debug_id(vertices[0], PrimitiveType::Vertex) == 0); + CHECK(m._debug_id(vertices[1], PrimitiveType::Vertex) == 1); + CHECK(m._debug_id(vertices[2], PrimitiveType::Vertex) == 2); + CHECK(m._debug_id(vertices[3], PrimitiveType::Vertex) == 3); + CHECK(m._debug_id(vertices[4], PrimitiveType::Vertex) == 4); + CHECK(m._debug_id(vertices[5], PrimitiveType::Vertex) == 5); + CHECK(m._debug_id(vertices[0], PrimitiveType::Edge) == 0); + CHECK(m._debug_id(vertices[5], PrimitiveType::Edge) == 4); + } + SECTION("edges") + { + const std::vector edges = m.get_all(PrimitiveType::Edge); + REQUIRE(edges.size() == 5); + } +} + +TEST_CASE("1D_loop_lines", "[tuple_generation], [tuple_1d]") +{ + DEBUG_EdgeMesh m = loop_lines(); + + SECTION("vertices") + { + const std::vector vertices = m.get_all(PrimitiveType::Vertex); + REQUIRE(vertices.size() == 6); + CHECK(m._debug_id(vertices[0], PrimitiveType::Vertex) == 0); + CHECK(m._debug_id(vertices[1], PrimitiveType::Vertex) == 1); + CHECK(m._debug_id(vertices[2], PrimitiveType::Vertex) == 2); + CHECK(m._debug_id(vertices[3], PrimitiveType::Vertex) == 3); + CHECK(m._debug_id(vertices[4], PrimitiveType::Vertex) == 4); + CHECK(m._debug_id(vertices[5], PrimitiveType::Vertex) == 5); + } + SECTION("edges") + { + const std::vector edges = m.get_all(PrimitiveType::Edge); + REQUIRE(edges.size() == 6); + } +} + + +TEST_CASE("1D_self_loop", "[tuple_generation], [tuple_1d]") +{ + DEBUG_EdgeMesh m = self_loop(); + + SECTION("vertices") + { + const std::vector vertices = m.get_all(PrimitiveType::Vertex); + REQUIRE(vertices.size() == 1); + CHECK(m._debug_id(vertices[0], PrimitiveType::Vertex) == 0); + } + SECTION("edges") + { + const std::vector edges = m.get_all(PrimitiveType::Edge); + REQUIRE(edges.size() == 1); + } +} + +TEST_CASE("1D_random_switches", "[tuple_operation],[tuple_1d]") +{ + // DEBUG_EdgeMesh m = single_line(); + // DEBUG_EdgeMesh m = multiple_lines(); + DEBUG_EdgeMesh m = loop_lines(); + // DEBUG_EdgeMesh m = two_line_loop(); + // DEBUG_EdgeMesh m = self_loop(); + + SECTION("vertices") + { + const std::vector vertex_tuples = m.get_all(PrimitiveType::Vertex); + for (size_t i = 0; i < vertex_tuples.size(); ++i) { + Tuple t = vertex_tuples[i]; + for (size_t j = 0; j < 10; j++) { + switch (rand() % 2) { + case 0: t = m.switch_tuple(t, PrimitiveType::Vertex); break; + case 1: + if (!m.is_boundary(t)) { + t = m.switch_tuple(t, PrimitiveType::Edge); + } + break; + default: break; + } + CHECK(m.is_valid_slow(t)); + } + } + } + + SECTION("edges") + { + const std::vector edge_tuples = m.get_all(PrimitiveType::Edge); + for (size_t i = 0; i < edge_tuples.size(); ++i) { + Tuple t = edge_tuples[i]; + for (size_t j = 0; j < 10; j++) { + switch (rand() % 2) { + case 0: t = m.switch_tuple(t, PrimitiveType::Vertex); break; + case 1: + if (!m.is_boundary(t)) { + t = m.switch_tuple(t, PrimitiveType::Edge); + } + break; + default: break; + } + CHECK(m.is_valid_slow(t)); + } + } + } +} + +TEST_CASE("1D_is_boundary", "[tuple_1d]") +{ + SECTION("single_line") + { + DEBUG_EdgeMesh m = single_line(); + + size_t n_boundary_vertices = 0; + for (const Tuple& v : m.get_all(PrimitiveType::Vertex)) { + if (m.is_boundary(v)) { + ++n_boundary_vertices; + } + } + + CHECK(n_boundary_vertices == 2); + } + + SECTION("multiple_lines") + { + DEBUG_EdgeMesh m = multiple_lines(); + + size_t n_boundary_vertices = 0; + for (const Tuple& v : m.get_all(PrimitiveType::Vertex)) { + if (m.is_boundary(v)) { + ++n_boundary_vertices; + } + } + + CHECK(n_boundary_vertices == 2); + } + + SECTION("loop_lines") + { + DEBUG_EdgeMesh m = loop_lines(); + + size_t n_boundary_vertices = 0; + for (const Tuple& v : m.get_all(PrimitiveType::Vertex)) { + if (m.is_boundary(v)) { + ++n_boundary_vertices; + } + } + + CHECK(n_boundary_vertices == 0); + } + + SECTION("two_line_loop") + { + DEBUG_EdgeMesh m = two_line_loop(); + + size_t n_boundary_vertices = 0; + for (const Tuple& v : m.get_all(PrimitiveType::Vertex)) { + if (m.is_boundary(v)) { + ++n_boundary_vertices; + } + } + + CHECK(n_boundary_vertices == 0); + } + + SECTION("self_loop") + { + DEBUG_EdgeMesh m = self_loop(); + + size_t n_boundary_vertices = 0; + for (const Tuple& v : m.get_all(PrimitiveType::Vertex)) { + if (m.is_boundary(v)) { + ++n_boundary_vertices; + } + } + + CHECK(n_boundary_vertices == 0); + } +} + +bool tuple_equal(const EdgeMesh& m, const Tuple& t0, const Tuple& t1) +{ + const auto l = wmtk::logger().level(); + wmtk::logger().set_level(spdlog::level::err); + const long v0 = m._debug_id(t0, PrimitiveType::Vertex); + const long e0 = m._debug_id(t0, PrimitiveType::Edge); + const long v1 = m._debug_id(t1, PrimitiveType::Vertex); + const long e1 = m._debug_id(t1, PrimitiveType::Edge); + wmtk::logger().set_level(l); + return (v0 == v1) && (e0 == e1); +} + +TEST_CASE("1D_double_switches", "[tuple_operation],[tuple_1d]") +{ + // checking for every tuple t: + // (1) t.switch_vertex().switch_vertex() == t + // (2) t.switch_edge().switch_edge() == t + + // DEBUG_EdgeMesh m = single_line(); + DEBUG_EdgeMesh m = multiple_lines(); + // DEBUG_EdgeMesh m = loop_lines(); + // DEBUG_EdgeMesh m = two_line_loop(); + // DEBUG_EdgeMesh m = self_loop(); + + SECTION("vertices") + { + const std::vector vertices = m.get_all(PrimitiveType::Vertex); + for (const auto& t : vertices) { + const Tuple t_after_v = m.switch_vertex(m.switch_vertex(t)); + CHECK(tuple_equal(m, t, t_after_v)); + if (!m.is_boundary(t)) { + const Tuple t_after_e = m.switch_edge(m.switch_edge(t)); + CHECK(tuple_equal(m, t, t_after_e)); + } + } + } + SECTION("edges") + { + const std::vector edges = m.get_all(PrimitiveType::Edge); + for (const auto& t : edges) { + const Tuple t_after_v = m.switch_vertex(m.switch_vertex(t)); + CHECK(tuple_equal(m, t, t_after_v)); + if (!m.is_boundary(t)) { + const Tuple t_after_e = m.switch_edge(m.switch_edge(t)); + CHECK(tuple_equal(m, t, t_after_e)); + } + } + } +} \ No newline at end of file From e43b2196fb5e49a9191ce47d9c0fb7a029ac1dce Mon Sep 17 00:00:00 2001 From: Leyi Zhu Date: Fri, 29 Sep 2023 09:22:29 -0400 Subject: [PATCH 34/49] collapse test add return_tuple check and delete simplex test --- tests/test_1d_operations.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tests/test_1d_operations.cpp b/tests/test_1d_operations.cpp index 5ce42ed0d2..a1cc665715 100644 --- a/tests/test_1d_operations.cpp +++ b/tests/test_1d_operations.cpp @@ -115,13 +115,12 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") Tuple edge = m.tuple_from_edge_id(edge_id); REQUIRE(m.is_valid_slow(edge)); const long vertex_id = m._debug_id(edge, PV); - std::cout << "edge_id = " << edge_id << "\t vertex_id = " << vertex_id << std::endl; Accessor hash_accessor = m.get_cell_hash_accessor(); auto executor = m.get_emoe(edge, hash_accessor); - CHECK(m.is_connectivity_valid()); const Tuple ret_tuple = executor.collapse_edge(); + CHECK(m.is_connectivity_valid()); CHECK(!ret_tuple.is_null()); // collapse operation is valid // check return tuple CHECK(m._debug_id(ret_tuple, PE) == 1); @@ -133,6 +132,8 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") const auto ve = m.create_base_accessor(m.ve_handle()); const auto ee = m.create_base_accessor(m.e_handle(PE)); const auto ev = m.create_base_accessor(m.e_handle(PV)); + // check ee, ev, ve + } SECTION("single_line") @@ -174,6 +175,7 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") const long edge_id = 0; Tuple edge = m.tuple_from_edge_id(edge_id); + const long vertex_id = m._debug_id(edge, PV); REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); auto executor = m.get_emoe(edge, hash_accessor); @@ -181,7 +183,11 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") const Tuple ret_tuple = executor.collapse_edge(); CHECK(!ret_tuple.is_null()); // collapse operation is valid // check return tuple - + CHECK(m._debug_id(ret_tuple, PE) == 1); + CHECK(m._debug_id(ret_tuple, PV) == 1); + // check delete + CHECK(m.is_simplex_deleted(PE, edge_id)); + CHECK(m.is_simplex_deleted(PV, vertex_id)); CHECK(m.is_connectivity_valid()); } @@ -192,6 +198,7 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") const long edge_id = 0; Tuple edge = m.tuple_from_edge_id(edge_id); + const long vertex_id = m._debug_id(edge, PV); REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); auto executor = m.get_emoe(edge, hash_accessor); @@ -199,6 +206,11 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") const Tuple ret_tuple = executor.collapse_edge(); CHECK(!ret_tuple.is_null()); // collapse operation is valid // check return tuple + CHECK(m._debug_id(ret_tuple, PE) == 5); + CHECK(m._debug_id(ret_tuple, PV) == 1); + // check delete + CHECK(m.is_simplex_deleted(PE, edge_id)); + CHECK(m.is_simplex_deleted(PV, vertex_id)); CHECK(m.is_connectivity_valid()); } @@ -213,6 +225,7 @@ TEST_CASE("split_edge_1D", "[operations][1D]") const long edge_id = 2; Tuple edge = m.tuple_from_edge_id(edge_id); + const long vertex_id = m._debug_id(edge, PV); REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); auto executor = m.get_emoe(edge, hash_accessor); From 4f596561cab1a2a6ed1668301ec5203ac5a773bd Mon Sep 17 00:00:00 2001 From: Leyi Zhu Date: Fri, 29 Sep 2023 09:45:02 -0400 Subject: [PATCH 35/49] fix bug in update ve in collapse edge --- src/wmtk/EdgeMeshOperationExecutor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wmtk/EdgeMeshOperationExecutor.cpp b/src/wmtk/EdgeMeshOperationExecutor.cpp index f92c3983c5..7e926dad3f 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.cpp +++ b/src/wmtk/EdgeMeshOperationExecutor.cpp @@ -210,7 +210,7 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge_single_mesh() // update ve { - ve_accessor.index_access().scalar_attribute(m_spine_vids[0]) = m_neighbor_eids[1]; + ve_accessor.index_access().scalar_attribute(m_spine_vids[1]) = m_neighbor_eids[1]; } update_cell_hash(); From e20fd218deedd94189621200b88eac36693f8a1d Mon Sep 17 00:00:00 2001 From: Leyi Zhu Date: Fri, 29 Sep 2023 10:00:15 -0400 Subject: [PATCH 36/49] finish testing collapse edge --- tests/test_1d_operations.cpp | 39 ++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/tests/test_1d_operations.cpp b/tests/test_1d_operations.cpp index a1cc665715..06aa73cf15 100644 --- a/tests/test_1d_operations.cpp +++ b/tests/test_1d_operations.cpp @@ -129,11 +129,15 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") CHECK(m.is_simplex_deleted(PE, edge_id)); CHECK(m.is_simplex_deleted(PV, vertex_id)); - const auto ve = m.create_base_accessor(m.ve_handle()); - const auto ee = m.create_base_accessor(m.e_handle(PE)); - const auto ev = m.create_base_accessor(m.e_handle(PV)); - // check ee, ev, ve - + auto ve = m.create_base_accessor(m.ve_handle()); + auto ee = m.create_base_accessor(m.e_handle(PE)); + auto ev = m.create_base_accessor(m.e_handle(PV)); + // check ve, ee, ev + CHECK(ve.scalar_attribute(3) == 3); + CHECK(ee.vector_attribute(1)[1] == 3); + CHECK(ee.vector_attribute(3)[0] == 1); + CHECK(ev.vector_attribute(1)[1] == 3); + CHECK(ev.vector_attribute(3)[0] == 3); } SECTION("single_line") @@ -181,6 +185,7 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") auto executor = m.get_emoe(edge, hash_accessor); const Tuple ret_tuple = executor.collapse_edge(); + CHECK(m.is_connectivity_valid()); CHECK(!ret_tuple.is_null()); // collapse operation is valid // check return tuple CHECK(m._debug_id(ret_tuple, PE) == 1); @@ -188,7 +193,16 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") // check delete CHECK(m.is_simplex_deleted(PE, edge_id)); CHECK(m.is_simplex_deleted(PV, vertex_id)); - CHECK(m.is_connectivity_valid()); + + auto ve = m.create_base_accessor(m.ve_handle()); + auto ee = m.create_base_accessor(m.e_handle(PE)); + auto ev = m.create_base_accessor(m.e_handle(PV)); + // check ve, ee, ev + CHECK(ve.scalar_attribute(1) == 1); + CHECK(ee.vector_attribute(1)[0] == 1); + CHECK(ee.vector_attribute(1)[1] == 1); + CHECK(ev.vector_attribute(1)[0] == 1); + CHECK(ev.vector_attribute(1)[1] == 1); } SECTION("loop_lines") @@ -204,6 +218,7 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") auto executor = m.get_emoe(edge, hash_accessor); const Tuple ret_tuple = executor.collapse_edge(); + CHECK(m.is_connectivity_valid()); CHECK(!ret_tuple.is_null()); // collapse operation is valid // check return tuple CHECK(m._debug_id(ret_tuple, PE) == 5); @@ -212,7 +227,16 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") CHECK(m.is_simplex_deleted(PE, edge_id)); CHECK(m.is_simplex_deleted(PV, vertex_id)); - CHECK(m.is_connectivity_valid()); + + auto ve = m.create_base_accessor(m.ve_handle()); + auto ee = m.create_base_accessor(m.e_handle(PE)); + auto ev = m.create_base_accessor(m.e_handle(PV)); + // check ve, ee, ev + CHECK(ve.scalar_attribute(1) == 1); + CHECK(ee.vector_attribute(1)[0] == 5); + CHECK(ee.vector_attribute(5)[1] == 1); + CHECK(ev.vector_attribute(1)[0] == 1); + CHECK(ev.vector_attribute(5)[1] == 1); } } @@ -225,7 +249,6 @@ TEST_CASE("split_edge_1D", "[operations][1D]") const long edge_id = 2; Tuple edge = m.tuple_from_edge_id(edge_id); - const long vertex_id = m._debug_id(edge, PV); REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); auto executor = m.get_emoe(edge, hash_accessor); From add571dd0c9683477d64688cbf037678e064211d Mon Sep 17 00:00:00 2001 From: Leyi Zhu Date: Fri, 29 Sep 2023 10:45:37 -0400 Subject: [PATCH 37/49] fix bug in split_edge ev update --- src/wmtk/EdgeMeshOperationExecutor.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/wmtk/EdgeMeshOperationExecutor.cpp b/src/wmtk/EdgeMeshOperationExecutor.cpp index 7e926dad3f..d2a7775ecd 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.cpp +++ b/src/wmtk/EdgeMeshOperationExecutor.cpp @@ -119,10 +119,12 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge_single_mesh() if (m_neighbor_eids[i] != -1) { auto ee_neighbor = ee_accessor.index_access().vector_attribute(m_neighbor_eids[i]); + auto ev_neighbor = + ev_accessor.index_access().vector_attribute(m_neighbor_eids[i]); for (long j = 0; j < 2; j++) { - if (ee_neighbor[j] == m_operating_edge_id) { + if (ee_neighbor[j] == m_operating_edge_id && ev_neighbor[j] == m_spine_vids[i]) { ee_neighbor[j] = new_eids[i]; - break; // must break here + break; } } } From 22c615a68f94511575e36da086e6f7a6cf2e4480 Mon Sep 17 00:00:00 2001 From: Eric Zhu Date: Fri, 29 Sep 2023 10:55:27 -0400 Subject: [PATCH 38/49] finish split test --- tests/test_1d_operations.cpp | 154 ++++++++++++++++++++++++++++++----- 1 file changed, 135 insertions(+), 19 deletions(-) diff --git a/tests/test_1d_operations.cpp b/tests/test_1d_operations.cpp index 06aa73cf15..0d598b2809 100644 --- a/tests/test_1d_operations.cpp +++ b/tests/test_1d_operations.cpp @@ -250,11 +250,39 @@ TEST_CASE("split_edge_1D", "[operations][1D]") const long edge_id = 2; Tuple edge = m.tuple_from_edge_id(edge_id); REQUIRE(m.is_valid_slow(edge)); + const long vertex_id = m._debug_id(edge, PV); + Accessor hash_accessor = m.get_cell_hash_accessor(); auto executor = m.get_emoe(edge, hash_accessor); - executor.split_edge(); + const Tuple ret_tuple = executor.split_edge(); CHECK(m.is_connectivity_valid()); + CHECK(!ret_tuple.is_null()); // split operation is valid + // check return tuple + CHECK(m._debug_id(ret_tuple, PE) == 5); + CHECK(m._debug_id(ret_tuple, PV) == vertex_id); + // check delete + CHECK(m.is_simplex_deleted(PE, edge_id)); + + auto ve = m.create_base_accessor(m.ve_handle()); + auto ee = m.create_base_accessor(m.e_handle(PE)); + auto ev = m.create_base_accessor(m.e_handle(PV)); + // check ve, ee, ev + CHECK(ve.scalar_attribute(3) == 6); + CHECK(ve.scalar_attribute(6) == 5); + CHECK(ve.scalar_attribute(2) == 5); + + CHECK(ee.vector_attribute(1)[1] == 5); + CHECK(ee.vector_attribute(5)[0] == 1); + CHECK(ee.vector_attribute(5)[1] == 6); + CHECK(ee.vector_attribute(6)[0] == 5); + CHECK(ee.vector_attribute(6)[1] == 3); + CHECK(ee.vector_attribute(3)[0] == 6); + + CHECK(ev.vector_attribute(5)[0] == 2); + CHECK(ev.vector_attribute(5)[1] == 6); + CHECK(ev.vector_attribute(6)[0] == 6); + CHECK(ev.vector_attribute(6)[1] == 3); } SECTION("single_line") @@ -264,12 +292,37 @@ TEST_CASE("split_edge_1D", "[operations][1D]") const long edge_id = 0; Tuple edge = m.tuple_from_edge_id(edge_id); + const long vertex_id = m._debug_id(edge, PV); REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); auto executor = m.get_emoe(edge, hash_accessor); - executor.split_edge(); + const Tuple ret_tuple = executor.split_edge(); CHECK(m.is_connectivity_valid()); + CHECK(!ret_tuple.is_null()); // split opearation is valid + // check return tuple + CHECK(m._debug_id(ret_tuple, PE) == 1); + CHECK(m._debug_id(ret_tuple, PV) == vertex_id); + // check delete + CHECK(m.is_simplex_deleted(PE, edge_id)); + + auto ve = m.create_base_accessor(m.ve_handle()); + auto ee = m.create_base_accessor(m.e_handle(PE)); + auto ev = m.create_base_accessor(m.e_handle(PV)); + // check ve, ee, ev + CHECK(ve.scalar_attribute(0) == 1); + CHECK(ve.scalar_attribute(2) == 1); + CHECK(ve.scalar_attribute(1) == 2); + + CHECK(ee.vector_attribute(1)[0] == -1); + CHECK(ee.vector_attribute(1)[1] == 2); + CHECK(ee.vector_attribute(2)[0] == 1); + CHECK(ee.vector_attribute(2)[1] == -1); + + CHECK(ev.vector_attribute(1)[0] == 0); + CHECK(ev.vector_attribute(1)[1] == 2); + CHECK(ev.vector_attribute(2)[0] == 2); + CHECK(ev.vector_attribute(2)[1] == 1); } SECTION("self_loop") @@ -279,42 +332,78 @@ TEST_CASE("split_edge_1D", "[operations][1D]") const long edge_id = 0; Tuple edge = m.tuple_from_edge_id(edge_id); + const long vertex_id = m._debug_id(edge, PV); REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); auto executor = m.get_emoe(edge, hash_accessor); - executor.split_edge(); + const Tuple ret_tuple = executor.split_edge(); CHECK(m.is_connectivity_valid()); - } + CHECK(!ret_tuple.is_null()); // split opearation is valid + // check return tuple + CHECK(m._debug_id(ret_tuple, PE) == 1); + CHECK(m._debug_id(ret_tuple, PV) == vertex_id); + // check delete + CHECK(m.is_simplex_deleted(PE, edge_id)); - SECTION("two_line_loop") - { - DEBUG_EdgeMesh m = two_line_loop(); - REQUIRE(m.is_connectivity_valid()); + auto ve = m.create_base_accessor(m.ve_handle()); + auto ee = m.create_base_accessor(m.e_handle(PE)); + auto ev = m.create_base_accessor(m.e_handle(PV)); + // check ve, ee, ev + CHECK(ve.scalar_attribute(0) == 2); + CHECK(ve.scalar_attribute(1) == 1); - const long edge_id = 0; - Tuple edge = m.tuple_from_edge_id(edge_id); - REQUIRE(m.is_valid_slow(edge)); - Accessor hash_accessor = m.get_cell_hash_accessor(); - auto executor = m.get_emoe(edge, hash_accessor); + CHECK(ee.vector_attribute(1)[0] == 2); + CHECK(ee.vector_attribute(1)[1] == 2); + CHECK(ee.vector_attribute(2)[0] == 1); + CHECK(ee.vector_attribute(2)[1] == 1); - executor.split_edge(); - CHECK(m.is_connectivity_valid()); + CHECK(ev.vector_attribute(1)[0] == 0); + CHECK(ev.vector_attribute(1)[1] == 1); + CHECK(ev.vector_attribute(2)[0] == 1); + CHECK(ev.vector_attribute(2)[1] == 0); } - SECTION("self_loop") + SECTION("two_line_loop") { - DEBUG_EdgeMesh m = self_loop(); + DEBUG_EdgeMesh m = two_line_loop(); REQUIRE(m.is_connectivity_valid()); const long edge_id = 0; Tuple edge = m.tuple_from_edge_id(edge_id); + const long vertex_id = m._debug_id(edge, PV); REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); auto executor = m.get_emoe(edge, hash_accessor); - executor.split_edge(); + const Tuple ret_tuple = executor.split_edge(); CHECK(m.is_connectivity_valid()); + CHECK(!ret_tuple.is_null()); // split operation is valid + // check return tuple + CHECK(m._debug_id(ret_tuple, PE) == 2); + CHECK(m._debug_id(ret_tuple, PV) == vertex_id); + // check delete + CHECK(m.is_simplex_deleted(PE, edge_id)); + + auto ve = m.create_base_accessor(m.ve_handle()); + auto ee = m.create_base_accessor(m.e_handle(PE)); + auto ev = m.create_base_accessor(m.e_handle(PV)); + // check ve, ee, ev + CHECK(ve.scalar_attribute(0) == 2); + CHECK(ve.scalar_attribute(1) == 3); + CHECK(ve.scalar_attribute(2) == 2); + + CHECK(ee.vector_attribute(1)[1] == 2); + CHECK(ee.vector_attribute(2)[0] == 1); + CHECK(ee.vector_attribute(2)[1] == 3); + CHECK(ee.vector_attribute(3)[0] == 2); + CHECK(ee.vector_attribute(3)[1] == 1); + CHECK(ee.vector_attribute(1)[0] == 3); + + CHECK(ev.vector_attribute(2)[0] == 0); + CHECK(ev.vector_attribute(2)[1] == 2); + CHECK(ev.vector_attribute(3)[0] == 2); + CHECK(ev.vector_attribute(3)[1] == 1); } SECTION("loop_lines") @@ -324,11 +413,38 @@ TEST_CASE("split_edge_1D", "[operations][1D]") const long edge_id = 0; Tuple edge = m.tuple_from_edge_id(edge_id); + const long vertex_id = m._debug_id(edge, PV); REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); auto executor = m.get_emoe(edge, hash_accessor); - executor.split_edge(); + const Tuple ret_tuple = executor.split_edge(); CHECK(m.is_connectivity_valid()); + CHECK(!ret_tuple.is_null()); // split operation is valid + // check return tuple + CHECK(m._debug_id(ret_tuple, PE) == 6); + CHECK(m._debug_id(ret_tuple, PV) == vertex_id); + // check delete + CHECK(m.is_simplex_deleted(PE, edge_id)); + + auto ve = m.create_base_accessor(m.ve_handle()); + auto ee = m.create_base_accessor(m.e_handle(PE)); + auto ev = m.create_base_accessor(m.e_handle(PV)); + // check ve, ee, ev + CHECK(ve.scalar_attribute(0) == 6); + CHECK(ve.scalar_attribute(1) == 7); + CHECK(ve.scalar_attribute(6) == 6); + + CHECK(ee.vector_attribute(5)[1] == 6); + CHECK(ee.vector_attribute(6)[0] == 5); + CHECK(ee.vector_attribute(6)[1] == 7); + CHECK(ee.vector_attribute(7)[0] == 6); + CHECK(ee.vector_attribute(7)[1] == 1); + CHECK(ee.vector_attribute(1)[0] == 7); + + CHECK(ev.vector_attribute(6)[0] == 0); + CHECK(ev.vector_attribute(6)[1] == 6); + CHECK(ev.vector_attribute(7)[0] == 6); + CHECK(ev.vector_attribute(7)[1] == 1); } } \ No newline at end of file From 3844c20fca9f0d4c3ab3d00955b33c2912b76ac7 Mon Sep 17 00:00:00 2001 From: JcDai Date: Tue, 3 Oct 2023 16:24:34 -0400 Subject: [PATCH 39/49] refactor based on comments --- src/wmtk/EdgeMesh.cpp | 6 + src/wmtk/EdgeMesh.hpp | 2 +- src/wmtk/EdgeMeshOperationExecutor.cpp | 16 +- src/wmtk/EdgeMeshOperationExecutor.hpp | 6 +- src/wmtk/Types.hpp | 2 +- .../edgemesh_topology_initialization.cpp | 4 +- tests/test_1d_operations.cpp | 42 +-- tests/test_topology.cpp | 167 +++-------- tests/test_tuple_1d.cpp | 265 +++++++----------- tests/tools/DEBUG_EdgeMesh.cpp | 11 +- 10 files changed, 200 insertions(+), 321 deletions(-) diff --git a/src/wmtk/EdgeMesh.cpp b/src/wmtk/EdgeMesh.cpp index f4b50f4f9c..5693ef0197 100644 --- a/src/wmtk/EdgeMesh.cpp +++ b/src/wmtk/EdgeMesh.cpp @@ -78,6 +78,12 @@ Tuple EdgeMesh::switch_tuple(const Tuple& tuple, PrimitiveType type) const auto ee = ee_accessor.vector_attribute(tuple); long gcid_new = ee(tuple.m_local_vid); + + // TODO: This is for special case self-loop, just to make sure the local vid of the returned + // tuple is the same as the input. (When doing double-switch this is needed) + if (gcid_new == tuple.m_global_cid) return tuple; + + long lvid_new = -1; ConstAccessor ev_accessor = create_const_accessor(m_ev_handle); diff --git a/src/wmtk/EdgeMesh.hpp b/src/wmtk/EdgeMesh.hpp index f1996cd2df..9784169d02 100644 --- a/src/wmtk/EdgeMesh.hpp +++ b/src/wmtk/EdgeMesh.hpp @@ -29,7 +29,7 @@ class EdgeMesh : public Mesh bool is_boundary_vertex(const Tuple& tuple) const override; bool is_boundary_edge(const Tuple& tuple) const override { - throw("This function doesn't make sense for edgemesh"); + throw("This function doesn't make sense for EdgeMesh"); } void initialize(Eigen::Ref E); diff --git a/src/wmtk/EdgeMeshOperationExecutor.cpp b/src/wmtk/EdgeMeshOperationExecutor.cpp index d2a7775ecd..8ebf8e3e89 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.cpp +++ b/src/wmtk/EdgeMeshOperationExecutor.cpp @@ -77,6 +77,7 @@ std::vector EdgeMesh::EdgeMeshOperationExecutor::prepare_operating_tuples const { // this function is designed as a helper for multi_mesh + throw("this function is not tested"); return MultiMeshManager::map_edge_tuple_to_all_children(m_mesh, m_operating_tuple); } @@ -106,14 +107,14 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge_single_mesh() // for 2 new edges auto ee_new_0 = ee_accessor.index_access().vector_attribute(new_eids[0]); auto ee_new_1 = ee_accessor.index_access().vector_attribute(new_eids[1]); - ee_new_0[(local_vid + 1) % 2] = new_eids[1]; + ee_new_0[local_vid ^ 1] = new_eids[1]; ee_new_1[local_vid] = new_eids[0]; if (m_is_self_loop) { ee_new_0[local_vid] = new_eids[1]; - ee_new_1[(local_vid + 1) % 2] = new_eids[0]; + ee_new_1[local_vid ^ 1] = new_eids[0]; } else { ee_new_0[local_vid] = m_neighbor_eids[0]; - ee_new_1[(local_vid + 1) % 2] = m_neighbor_eids[1]; + ee_new_1[local_vid ^ 1] = m_neighbor_eids[1]; // for neighbor edges for (long i = 0; i < 2; i++) { if (m_neighbor_eids[i] != -1) { @@ -122,7 +123,8 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge_single_mesh() auto ev_neighbor = ev_accessor.index_access().vector_attribute(m_neighbor_eids[i]); for (long j = 0; j < 2; j++) { - if (ee_neighbor[j] == m_operating_edge_id && ev_neighbor[j] == m_spine_vids[i]) { + if (ee_neighbor[j] == m_operating_edge_id && + ev_neighbor[j] == m_spine_vids[i]) { ee_neighbor[j] = new_eids[i]; break; } @@ -138,9 +140,9 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge_single_mesh() auto ev_new_0 = ev_accessor.index_access().vector_attribute(new_eids[0]); auto ev_new_1 = ev_accessor.index_access().vector_attribute(new_eids[1]); ev_new_0[local_vid] = m_spine_vids[0]; - ev_new_0[(local_vid + 1) % 2] = v_new; + ev_new_0[local_vid ^ 1] = v_new; ev_new_1[local_vid] = v_new; - ev_new_1[(local_vid + 1) % 2] = m_spine_vids[1]; + ev_new_1[local_vid ^ 1] = m_spine_vids[1]; } // update ve @@ -189,7 +191,7 @@ Tuple EdgeMesh::EdgeMeshOperationExecutor::collapse_edge_single_mesh() auto ee_neighbor = ee_accessor.index_access().vector_attribute(m_neighbor_eids[i]); for (long j = 0; j < 2; j++) { if (ee_neighbor[j] == m_operating_edge_id) { - ee_neighbor[j] = m_neighbor_eids[(i + 1) % 2]; + ee_neighbor[j] = m_neighbor_eids[i ^ 1]; break; } } diff --git a/src/wmtk/EdgeMeshOperationExecutor.hpp b/src/wmtk/EdgeMeshOperationExecutor.hpp index 58b45e5b3e..1bab89d288 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.hpp +++ b/src/wmtk/EdgeMeshOperationExecutor.hpp @@ -20,7 +20,7 @@ class EdgeMesh::EdgeMeshOperationExecutor /** * @brief gather all simplices that are deleted in a split * - * The deleted simplices are exactly the open star of the edge + * The deleted simplex is the edge itself */ static const std::array, 2> get_split_simplices_to_delete( const Tuple& tuple, @@ -29,9 +29,7 @@ class EdgeMesh::EdgeMeshOperationExecutor /** * @brief gather all simplices that are deleted in a collapse * - * The deleted simplices are the intersection of the open star of the vertex and the closed star - * of the edge. This comes down to one vertex, three edges, and two faces if the edge is on the - * interior. On the boundary it is one vertex, two edges, and one face. + * The deleted simplices are the vertex and the edge of the input tuple */ static const std::array, 2> get_collapse_simplices_to_delete( const Tuple& tuple, diff --git a/src/wmtk/Types.hpp b/src/wmtk/Types.hpp index eae2e90444..a1421e87e9 100644 --- a/src/wmtk/Types.hpp +++ b/src/wmtk/Types.hpp @@ -3,8 +3,8 @@ #include namespace wmtk { -using RowVectors3l = Eigen::Matrix; using RowVectors2l = Eigen::Matrix; +using RowVectors3l = Eigen::Matrix; using VectorXl = Eigen::Matrix; using RowVectors4l = Eigen::Matrix; using RowVectors6l = Eigen::Matrix; diff --git a/src/wmtk/utils/edgemesh_topology_initialization.cpp b/src/wmtk/utils/edgemesh_topology_initialization.cpp index 5fa8bd98cf..ca9b595b04 100644 --- a/src/wmtk/utils/edgemesh_topology_initialization.cpp +++ b/src/wmtk/utils/edgemesh_topology_initialization.cpp @@ -11,7 +11,7 @@ std::tuple edgemesh_topology_initialization( RowVectors2l EE; VectorXl VE; - long vertex_count = E.maxCoeff() + 1; + const long vertex_count = E.maxCoeff() + 1; // store the complete vertex-edge connnectivity std::vector> complete_VE(vertex_count); @@ -38,7 +38,7 @@ std::tuple edgemesh_topology_initialization( } } else { // non-boundary vertex - for (int k = 0; k < 2; ++k) { + for (long k = 0; k < 2; ++k) { if (E(complete_VE[i][k], 0) == i) { EE(complete_VE[i][k], 0) = complete_VE[i][1 - k]; } diff --git a/tests/test_1d_operations.cpp b/tests/test_1d_operations.cpp index 0d598b2809..0ad9cfec84 100644 --- a/tests/test_1d_operations.cpp +++ b/tests/test_1d_operations.cpp @@ -29,8 +29,9 @@ TEST_CASE("simplices_to_delete_for_split_1D", "[operations][1D]") const long edge_id = 0; Tuple edge = m.tuple_from_edge_id(edge_id); - REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); + REQUIRE(m.is_valid(edge, hash_accessor)); + auto executor = m.get_emoe(edge, hash_accessor); executor.split_edge(); @@ -48,8 +49,9 @@ TEST_CASE("simplices_to_delete_for_split_1D", "[operations][1D]") const long edge_id = 0; Tuple edge = m.tuple_from_edge_id(edge_id); - REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); + REQUIRE(m.is_valid(edge, hash_accessor)); + auto executor = m.get_emoe(edge, hash_accessor); executor.split_edge(); @@ -70,8 +72,8 @@ TEST_CASE("simplices_to_delete_for_collapse_1D", "[operations][1D]") const long edge_id = 2; Tuple edge = m.tuple_from_edge_id(edge_id); - REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); + REQUIRE(m.is_valid(edge, hash_accessor)); auto executor = m.get_emoe(edge, hash_accessor); executor.collapse_edge(); @@ -90,8 +92,8 @@ TEST_CASE("simplices_to_delete_for_collapse_1D", "[operations][1D]") const long edge_id = 0; Tuple edge = m.tuple_from_edge_id(edge_id); - REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); + REQUIRE(m.is_valid(edge, hash_accessor)); auto executor = m.get_emoe(edge, hash_accessor); executor.collapse_edge(); @@ -113,10 +115,11 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") const long edge_id = 2; Tuple edge = m.tuple_from_edge_id(edge_id); - REQUIRE(m.is_valid_slow(edge)); - const long vertex_id = m._debug_id(edge, PV); Accessor hash_accessor = m.get_cell_hash_accessor(); + REQUIRE(m.is_valid(edge, hash_accessor)); + const long vertex_id = m._debug_id(edge, PV); + auto executor = m.get_emoe(edge, hash_accessor); const Tuple ret_tuple = executor.collapse_edge(); @@ -147,8 +150,9 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") const long edge_id = 0; Tuple edge = m.tuple_from_edge_id(edge_id); - REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); + REQUIRE(m.is_valid(edge, hash_accessor)); + auto executor = m.get_emoe(edge, hash_accessor); const Tuple ret_tuple = executor.collapse_edge(); @@ -163,8 +167,8 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") const long edge_id = 0; Tuple edge = m.tuple_from_edge_id(edge_id); - REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); + REQUIRE(m.is_valid(edge, hash_accessor)); auto executor = m.get_emoe(edge, hash_accessor); const Tuple ret_tuple = executor.collapse_edge(); @@ -180,8 +184,9 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") const long edge_id = 0; Tuple edge = m.tuple_from_edge_id(edge_id); const long vertex_id = m._debug_id(edge, PV); - REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); + REQUIRE(m.is_valid(edge, hash_accessor)); + auto executor = m.get_emoe(edge, hash_accessor); const Tuple ret_tuple = executor.collapse_edge(); @@ -213,8 +218,10 @@ TEST_CASE("collapse_edge_1D", "[operations][1D]") const long edge_id = 0; Tuple edge = m.tuple_from_edge_id(edge_id); const long vertex_id = m._debug_id(edge, PV); - REQUIRE(m.is_valid_slow(edge)); + Accessor hash_accessor = m.get_cell_hash_accessor(); + REQUIRE(m.is_valid(edge, hash_accessor)); + auto executor = m.get_emoe(edge, hash_accessor); const Tuple ret_tuple = executor.collapse_edge(); @@ -249,10 +256,11 @@ TEST_CASE("split_edge_1D", "[operations][1D]") const long edge_id = 2; Tuple edge = m.tuple_from_edge_id(edge_id); - REQUIRE(m.is_valid_slow(edge)); - const long vertex_id = m._debug_id(edge, PV); Accessor hash_accessor = m.get_cell_hash_accessor(); + REQUIRE(m.is_valid(edge, hash_accessor)); + const long vertex_id = m._debug_id(edge, PV); + auto executor = m.get_emoe(edge, hash_accessor); const Tuple ret_tuple = executor.split_edge(); @@ -293,8 +301,8 @@ TEST_CASE("split_edge_1D", "[operations][1D]") const long edge_id = 0; Tuple edge = m.tuple_from_edge_id(edge_id); const long vertex_id = m._debug_id(edge, PV); - REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); + REQUIRE(m.is_valid(edge, hash_accessor)); auto executor = m.get_emoe(edge, hash_accessor); const Tuple ret_tuple = executor.split_edge(); @@ -333,8 +341,8 @@ TEST_CASE("split_edge_1D", "[operations][1D]") const long edge_id = 0; Tuple edge = m.tuple_from_edge_id(edge_id); const long vertex_id = m._debug_id(edge, PV); - REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); + REQUIRE(m.is_valid(edge, hash_accessor)); auto executor = m.get_emoe(edge, hash_accessor); const Tuple ret_tuple = executor.split_edge(); @@ -372,8 +380,9 @@ TEST_CASE("split_edge_1D", "[operations][1D]") const long edge_id = 0; Tuple edge = m.tuple_from_edge_id(edge_id); const long vertex_id = m._debug_id(edge, PV); - REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); + REQUIRE(m.is_valid(edge, hash_accessor)); + auto executor = m.get_emoe(edge, hash_accessor); const Tuple ret_tuple = executor.split_edge(); @@ -414,8 +423,9 @@ TEST_CASE("split_edge_1D", "[operations][1D]") const long edge_id = 0; Tuple edge = m.tuple_from_edge_id(edge_id); const long vertex_id = m._debug_id(edge, PV); - REQUIRE(m.is_valid_slow(edge)); Accessor hash_accessor = m.get_cell_hash_accessor(); + REQUIRE(m.is_valid(edge, hash_accessor)); + auto executor = m.get_emoe(edge, hash_accessor); const Tuple ret_tuple = executor.split_edge(); diff --git a/tests/test_topology.cpp b/tests/test_topology.cpp index 0dcfaf5e8f..40644a9ef1 100644 --- a/tests/test_topology.cpp +++ b/tests/test_topology.cpp @@ -336,111 +336,51 @@ TEST_CASE("topology_of_tet_bunny", "[topology][3D]") } } -TEST_CASE("topology_of_single_line", "[topology][1D]") +TEST_CASE("topology_test_1d", "[topology][1D]") { - /* - 0 ---- 1 - */ - Eigen::Matrix E; - E << 0, 1; - auto [EE, VE] = edgemesh_topology_initialization(E); - - // std::cout << "EV:\n" << E << std::endl; - // std::cout << "EE:\n" << EE << std::endl; - // std::cout << "VE:\n" << VE << std::endl; - - // 1. Test relationship between VE and EV - for (int i = 0; i < VE.size(); ++i) { - CHECK((E.row(VE(i)).array() == i).any()); + Eigen::Matrix E; + SECTION("single_line") + { + /* + 0 ---- 1 + */ + E.resize(1, 2); + E << 0, 1; } - - // 2. Test relationship between EV and EE - for (int i = 0; i < EE.rows(); ++i) { - for (int j = 0; j < 2; ++j) { - long nb = EE(i, j); - if (nb < 0) continue; - - CHECK((EE.row(nb).array() == i).any()); - - // TODO add checks - } + SECTION("multiple_lines") + { + /* + 5 -- 2 -- 0 -- 1 -- 4 -- 3 + */ + E.resize(5, 2); + E << 0, 1, 1, 4, 3, 4, 2, 0, 5, 2; } -} - -TEST_CASE("topology_of_multiple_lines", "[topology][1D]") -{ - /* - 5 -- 2 -- 0 -- 1 -- 4 -- 3 - */ - Eigen::Matrix E; - E << 0, 1, 1, 4, 3, 4, 2, 0, 5, 2; - auto [EE, VE] = edgemesh_topology_initialization(E); - - // std::cout << "EV:\n" << E << std::endl; - // std::cout << "EE:\n" << EE << std::endl; - // std::cout << "VE:\n" << VE << std::endl; - - // 1. Test relationship between VE and EV - for (int i = 0; i < VE.size(); ++i) { - CHECK((E.row(VE(i)).array() == i).any()); + SECTION("loop_lines") + { + /* + 5 -- 2 -- 0 -- 1 -- 4 -- 3 -- 5* + */ + E.resize(6, 2); + E << 0, 1, 1, 4, 3, 4, 2, 0, 5, 2, 5, 3; } - - // 2. Test relationship between EV and EE - for (int i = 0; i < EE.rows(); ++i) { - for (int j = 0; j < 2; ++j) { - long nb = EE(i, j); - if (nb < 0) continue; - - CHECK((EE.row(nb).array() == i).any()); - - // TODO add checks - } - } -} - -TEST_CASE("topology_of_loop", "[topology][1D]") -{ - /* - 5 -- 2 -- 0 -- 1 -- 4 -- 3 -- 5* - */ - Eigen::Matrix E; - E << 0, 1, 1, 4, 3, 4, 2, 0, 5, 2, 5, 3; - auto [EE, VE] = edgemesh_topology_initialization(E); - - // std::cout << "EV:\n" << E << std::endl; - // std::cout << "EE:\n" << EE << std::endl; - // std::cout << "VE:\n" << VE << std::endl; - - // 1. Test relationship between VE and EV - for (int i = 0; i < VE.size(); ++i) { - CHECK((E.row(VE(i)).array() == i).any()); + SECTION("two_line_loop") + { + /* + 0 -- 1 -- 0* + */ + E.resize(2, 2); + E << 0, 1, 1, 0; } - - // 2. Test relationship between EV and EE - for (int i = 0; i < EE.rows(); ++i) { - for (int j = 0; j < 2; ++j) { - long nb = EE(i, j); - if (nb < 0) continue; - - CHECK((EE.row(nb).array() == i).any()); - - // TODO add checks - } + SECTION("self_loop") + { + /* + 0 -- 0* + */ + E.resize(1, 2); + E << 0, 0; } -} -TEST_CASE("topology_of_two_line_loop", "[topology][1D]") -{ - /* - 0 -- 1 -- 0* - */ - Eigen::Matrix E; - E << 0, 1, 1, 0; - auto [EE, VE] = edgemesh_topology_initialization(E); - - std::cout << "EV:\n" << E << std::endl; - std::cout << "EE:\n" << EE << std::endl; - std::cout << "VE:\n" << VE << std::endl; + const auto [EE, VE] = edgemesh_topology_initialization(E); // 1. Test relationship between VE and EV for (int i = 0; i < VE.size(); ++i) { @@ -459,34 +399,3 @@ TEST_CASE("topology_of_two_line_loop", "[topology][1D]") } } } - -TEST_CASE("topology_of_self_loop", "[topology][1D]") -{ - /* - 0 -- 0* - */ - Eigen::Matrix E; - E << 0, 0; - auto [EE, VE] = edgemesh_topology_initialization(E); - - std::cout << "EV:\n" << E << std::endl; - std::cout << "EE:\n" << EE << std::endl; - std::cout << "VE:\n" << VE << std::endl; - - // 1. Test relationship between VE and EV - for (int i = 0; i < VE.size(); ++i) { - CHECK((E.row(VE(i)).array() == i).any()); - } - - // 2. Test relationship between EV and EE - for (int i = 0; i < EE.rows(); ++i) { - for (int j = 0; j < 2; ++j) { - long nb = EE(i, j); - if (nb < 0) continue; - - CHECK((EE.row(nb).array() == i).any()); - - // TODO add checks - } - } -} \ No newline at end of file diff --git a/tests/test_tuple_1d.cpp b/tests/test_tuple_1d.cpp index e4ba68d871..cc1ed01bbd 100644 --- a/tests/test_tuple_1d.cpp +++ b/tests/test_tuple_1d.cpp @@ -12,102 +12,72 @@ using namespace wmtk::tests; TEST_CASE("1D_initialize", "[mesh_creation],[tuple_1d]") { + DEBUG_EdgeMesh m; + std::vector edges, vertices; + SECTION("init from RowVectors2l") { - DEBUG_EdgeMesh m; RowVectors2l lines; lines.resize(3, 2); lines << 0, 1, 1, 2, 2, 3; m.initialize(lines); - const std::vector vertices = m.get_all(PrimitiveType::Vertex); + vertices = m.get_all(PrimitiveType::Vertex); REQUIRE(vertices.size() == 4); - const std::vector edges = m.get_all(PrimitiveType::Edge); + edges = m.get_all(PrimitiveType::Edge); REQUIRE(edges.size() == 3); REQUIRE(m.is_connectivity_valid()); - - const Tuple t0 = edges[0]; - const Tuple t1 = edges[1]; - const Tuple t2 = edges[2]; - REQUIRE(m.is_valid_slow(t0)); - REQUIRE(m.is_valid_slow(t1)); - REQUIRE(m.is_valid_slow(t2)); } SECTION("init single line") { - DEBUG_EdgeMesh m = single_line(); + m = single_line(); - const std::vector vertices = m.get_all(PrimitiveType::Vertex); + vertices = m.get_all(PrimitiveType::Vertex); REQUIRE(vertices.size() == 2); - const std::vector edges = m.get_all(PrimitiveType::Edge); + edges = m.get_all(PrimitiveType::Edge); REQUIRE(edges.size() == 1); REQUIRE(m.is_connectivity_valid()); - - const Tuple t = edges[0]; - REQUIRE(m.is_valid_slow(t)); } SECTION("init multiple lines") { - DEBUG_EdgeMesh m = multiple_lines(); + m = multiple_lines(); - const std::vector vertices = m.get_all(PrimitiveType::Vertex); + vertices = m.get_all(PrimitiveType::Vertex); REQUIRE(vertices.size() == 6); - const std::vector edges = m.get_all(PrimitiveType::Edge); + edges = m.get_all(PrimitiveType::Edge); REQUIRE(edges.size() == 5); REQUIRE(m.is_connectivity_valid()); - - const Tuple t0 = edges[0]; - const Tuple t1 = edges[1]; - const Tuple t2 = edges[2]; - const Tuple t3 = edges[3]; - const Tuple t4 = edges[4]; - REQUIRE(m.is_valid_slow(t0)); - REQUIRE(m.is_valid_slow(t1)); - REQUIRE(m.is_valid_slow(t2)); - REQUIRE(m.is_valid_slow(t3)); - REQUIRE(m.is_valid_slow(t4)); } SECTION("init loop lines") { - DEBUG_EdgeMesh m = loop_lines(); + m = loop_lines(); - const std::vector vertices = m.get_all(PrimitiveType::Vertex); + vertices = m.get_all(PrimitiveType::Vertex); REQUIRE(vertices.size() == 6); - const std::vector edges = m.get_all(PrimitiveType::Edge); + edges = m.get_all(PrimitiveType::Edge); REQUIRE(edges.size() == 6); REQUIRE(m.is_connectivity_valid()); - - const Tuple t0 = edges[0]; - const Tuple t1 = edges[1]; - const Tuple t2 = edges[2]; - const Tuple t3 = edges[3]; - const Tuple t4 = edges[4]; - const Tuple t5 = edges[5]; - REQUIRE(m.is_valid_slow(t0)); - REQUIRE(m.is_valid_slow(t1)); - REQUIRE(m.is_valid_slow(t2)); - REQUIRE(m.is_valid_slow(t3)); - REQUIRE(m.is_valid_slow(t4)); - REQUIRE(m.is_valid_slow(t5)); } SECTION("init self loop") { - DEBUG_EdgeMesh m = self_loop(); + m = self_loop(); - const std::vector vertices = m.get_all(PrimitiveType::Vertex); + vertices = m.get_all(PrimitiveType::Vertex); REQUIRE(vertices.size() == 1); - const std::vector edges = m.get_all(PrimitiveType::Edge); + edges = m.get_all(PrimitiveType::Edge); REQUIRE(edges.size() == 1); REQUIRE(m.is_connectivity_valid()); + } - const Tuple t0 = edges[0]; - REQUIRE(m.is_valid_slow(t0)); + auto const_hash_accessor = m.get_const_cell_hash_accessor(); + for (size_t i = 0; i < edges.size(); ++i) { + REQUIRE(m.is_valid(edges[i], const_hash_accessor)); } } @@ -119,10 +89,10 @@ TEST_CASE("1D_single_line", "[tuple_generation], [tuple_1d]") { const std::vector vertices = m.get_all(PrimitiveType::Vertex); REQUIRE(vertices.size() == 2); - CHECK(m._debug_id(vertices[0], PrimitiveType::Vertex) == 0); - CHECK(m._debug_id(vertices[1], PrimitiveType::Vertex) == 1); - CHECK(m._debug_id(vertices[0], PrimitiveType::Edge) == 0); - CHECK(m._debug_id(vertices[1], PrimitiveType::Edge) == 0); + CHECK(m.id(vertices[0], PrimitiveType::Vertex) == 0); + CHECK(m.id(vertices[1], PrimitiveType::Vertex) == 1); + CHECK(m.id(vertices[0], PrimitiveType::Edge) == 0); + CHECK(m.id(vertices[1], PrimitiveType::Edge) == 0); } SECTION("edges") { @@ -139,19 +109,24 @@ TEST_CASE("1D_multiple_lines", "[tuple_generation], [tuple_1d]") { const std::vector vertices = m.get_all(PrimitiveType::Vertex); REQUIRE(vertices.size() == 6); - CHECK(m._debug_id(vertices[0], PrimitiveType::Vertex) == 0); - CHECK(m._debug_id(vertices[1], PrimitiveType::Vertex) == 1); - CHECK(m._debug_id(vertices[2], PrimitiveType::Vertex) == 2); - CHECK(m._debug_id(vertices[3], PrimitiveType::Vertex) == 3); - CHECK(m._debug_id(vertices[4], PrimitiveType::Vertex) == 4); - CHECK(m._debug_id(vertices[5], PrimitiveType::Vertex) == 5); - CHECK(m._debug_id(vertices[0], PrimitiveType::Edge) == 0); - CHECK(m._debug_id(vertices[5], PrimitiveType::Edge) == 4); + CHECK(m.id(vertices[0], PrimitiveType::Vertex) == 0); + CHECK(m.id(vertices[1], PrimitiveType::Vertex) == 1); + CHECK(m.id(vertices[2], PrimitiveType::Vertex) == 2); + CHECK(m.id(vertices[3], PrimitiveType::Vertex) == 3); + CHECK(m.id(vertices[4], PrimitiveType::Vertex) == 4); + CHECK(m.id(vertices[5], PrimitiveType::Vertex) == 5); + CHECK(m.id(vertices[0], PrimitiveType::Edge) == 0); + CHECK(m.id(vertices[5], PrimitiveType::Edge) == 4); } SECTION("edges") { const std::vector edges = m.get_all(PrimitiveType::Edge); REQUIRE(edges.size() == 5); + CHECK(m.id(edges[0], PrimitiveType::Edge) == 0); + CHECK(m.id(edges[1], PrimitiveType::Edge) == 1); + CHECK(m.id(edges[2], PrimitiveType::Edge) == 2); + CHECK(m.id(edges[3], PrimitiveType::Edge) == 3); + CHECK(m.id(edges[4], PrimitiveType::Edge) == 4); } } @@ -163,17 +138,23 @@ TEST_CASE("1D_loop_lines", "[tuple_generation], [tuple_1d]") { const std::vector vertices = m.get_all(PrimitiveType::Vertex); REQUIRE(vertices.size() == 6); - CHECK(m._debug_id(vertices[0], PrimitiveType::Vertex) == 0); - CHECK(m._debug_id(vertices[1], PrimitiveType::Vertex) == 1); - CHECK(m._debug_id(vertices[2], PrimitiveType::Vertex) == 2); - CHECK(m._debug_id(vertices[3], PrimitiveType::Vertex) == 3); - CHECK(m._debug_id(vertices[4], PrimitiveType::Vertex) == 4); - CHECK(m._debug_id(vertices[5], PrimitiveType::Vertex) == 5); + CHECK(m.id(vertices[0], PrimitiveType::Vertex) == 0); + CHECK(m.id(vertices[1], PrimitiveType::Vertex) == 1); + CHECK(m.id(vertices[2], PrimitiveType::Vertex) == 2); + CHECK(m.id(vertices[3], PrimitiveType::Vertex) == 3); + CHECK(m.id(vertices[4], PrimitiveType::Vertex) == 4); + CHECK(m.id(vertices[5], PrimitiveType::Vertex) == 5); } SECTION("edges") { const std::vector edges = m.get_all(PrimitiveType::Edge); REQUIRE(edges.size() == 6); + CHECK(m.id(edges[0], PrimitiveType::Edge) == 0); + CHECK(m.id(edges[1], PrimitiveType::Edge) == 1); + CHECK(m.id(edges[2], PrimitiveType::Edge) == 2); + CHECK(m.id(edges[3], PrimitiveType::Edge) == 3); + CHECK(m.id(edges[4], PrimitiveType::Edge) == 4); + CHECK(m.id(edges[5], PrimitiveType::Edge) == 5); } } @@ -197,11 +178,7 @@ TEST_CASE("1D_self_loop", "[tuple_generation], [tuple_1d]") TEST_CASE("1D_random_switches", "[tuple_operation],[tuple_1d]") { - // DEBUG_EdgeMesh m = single_line(); - // DEBUG_EdgeMesh m = multiple_lines(); DEBUG_EdgeMesh m = loop_lines(); - // DEBUG_EdgeMesh m = two_line_loop(); - // DEBUG_EdgeMesh m = self_loop(); SECTION("vertices") { @@ -246,87 +223,48 @@ TEST_CASE("1D_random_switches", "[tuple_operation],[tuple_1d]") TEST_CASE("1D_is_boundary", "[tuple_1d]") { + DEBUG_EdgeMesh m; + size_t n_boundary_vertices_expected = std::numeric_limits::max(); + SECTION("single_line") { - DEBUG_EdgeMesh m = single_line(); - - size_t n_boundary_vertices = 0; - for (const Tuple& v : m.get_all(PrimitiveType::Vertex)) { - if (m.is_boundary(v)) { - ++n_boundary_vertices; - } - } - - CHECK(n_boundary_vertices == 2); + m = single_line(); + n_boundary_vertices_expected = 2; } SECTION("multiple_lines") { - DEBUG_EdgeMesh m = multiple_lines(); - - size_t n_boundary_vertices = 0; - for (const Tuple& v : m.get_all(PrimitiveType::Vertex)) { - if (m.is_boundary(v)) { - ++n_boundary_vertices; - } - } - - CHECK(n_boundary_vertices == 2); + m = multiple_lines(); + n_boundary_vertices_expected = 2; } SECTION("loop_lines") { - DEBUG_EdgeMesh m = loop_lines(); - - size_t n_boundary_vertices = 0; - for (const Tuple& v : m.get_all(PrimitiveType::Vertex)) { - if (m.is_boundary(v)) { - ++n_boundary_vertices; - } - } - - CHECK(n_boundary_vertices == 0); + m = loop_lines(); + n_boundary_vertices_expected = 0; } SECTION("two_line_loop") { - DEBUG_EdgeMesh m = two_line_loop(); - - size_t n_boundary_vertices = 0; - for (const Tuple& v : m.get_all(PrimitiveType::Vertex)) { - if (m.is_boundary(v)) { - ++n_boundary_vertices; - } - } - - CHECK(n_boundary_vertices == 0); + m = two_line_loop(); + n_boundary_vertices_expected = 0; } SECTION("self_loop") { - DEBUG_EdgeMesh m = self_loop(); + m = self_loop(); + n_boundary_vertices_expected = 0; + } - size_t n_boundary_vertices = 0; - for (const Tuple& v : m.get_all(PrimitiveType::Vertex)) { - if (m.is_boundary(v)) { - ++n_boundary_vertices; - } + // count boundary vertices + size_t n_boundary_vertices = 0; + for (const Tuple& v : m.get_all(PrimitiveType::Vertex)) { + if (m.is_boundary(v)) { + ++n_boundary_vertices; } - - CHECK(n_boundary_vertices == 0); } -} -bool tuple_equal(const EdgeMesh& m, const Tuple& t0, const Tuple& t1) -{ - const auto l = wmtk::logger().level(); - wmtk::logger().set_level(spdlog::level::err); - const long v0 = m._debug_id(t0, PrimitiveType::Vertex); - const long e0 = m._debug_id(t0, PrimitiveType::Edge); - const long v1 = m._debug_id(t1, PrimitiveType::Vertex); - const long e1 = m._debug_id(t1, PrimitiveType::Edge); - wmtk::logger().set_level(l); - return (v0 == v1) && (e0 == e1); + CHECK(n_boundary_vertices == n_boundary_vertices_expected); } TEST_CASE("1D_double_switches", "[tuple_operation],[tuple_1d]") @@ -335,34 +273,47 @@ TEST_CASE("1D_double_switches", "[tuple_operation],[tuple_1d]") // (1) t.switch_vertex().switch_vertex() == t // (2) t.switch_edge().switch_edge() == t - // DEBUG_EdgeMesh m = single_line(); - DEBUG_EdgeMesh m = multiple_lines(); - // DEBUG_EdgeMesh m = loop_lines(); - // DEBUG_EdgeMesh m = two_line_loop(); - // DEBUG_EdgeMesh m = self_loop(); - - SECTION("vertices") + DEBUG_EdgeMesh m; + SECTION("single_line") { - const std::vector vertices = m.get_all(PrimitiveType::Vertex); - for (const auto& t : vertices) { - const Tuple t_after_v = m.switch_vertex(m.switch_vertex(t)); - CHECK(tuple_equal(m, t, t_after_v)); - if (!m.is_boundary(t)) { - const Tuple t_after_e = m.switch_edge(m.switch_edge(t)); - CHECK(tuple_equal(m, t, t_after_e)); - } - } + m = single_line(); } - SECTION("edges") + SECTION("multiple_lines") { - const std::vector edges = m.get_all(PrimitiveType::Edge); - for (const auto& t : edges) { - const Tuple t_after_v = m.switch_vertex(m.switch_vertex(t)); - CHECK(tuple_equal(m, t, t_after_v)); - if (!m.is_boundary(t)) { - const Tuple t_after_e = m.switch_edge(m.switch_edge(t)); - CHECK(tuple_equal(m, t, t_after_e)); - } + m = multiple_lines(); + } + SECTION("two_line_loop") + { + m = two_line_loop(); + } + SECTION("loop_lines") + { + m = loop_lines(); + } + SECTION("self_loop") + { + m = self_loop(); + } + + // vertices + const std::vector vertices = m.get_all(PrimitiveType::Vertex); + for (const auto& t : vertices) { + const Tuple t_after_v = m.switch_vertex(m.switch_vertex(t)); + CHECK(t == t_after_v); + if (!m.is_boundary(t)) { + const Tuple t_after_e = m.switch_edge(m.switch_edge(t)); + CHECK(t == t_after_e); + } + } + + // edges + const std::vector edges = m.get_all(PrimitiveType::Edge); + for (const auto& t : edges) { + const Tuple t_after_v = m.switch_vertex(m.switch_vertex(t)); + CHECK(t == t_after_v); + if (!m.is_boundary(t)) { + const Tuple t_after_e = m.switch_edge(m.switch_edge(t)); + CHECK(t == t_after_e); } } } \ No newline at end of file diff --git a/tests/tools/DEBUG_EdgeMesh.cpp b/tests/tools/DEBUG_EdgeMesh.cpp index 598767d0f2..f626ca486b 100644 --- a/tests/tools/DEBUG_EdgeMesh.cpp +++ b/tests/tools/DEBUG_EdgeMesh.cpp @@ -3,9 +3,9 @@ namespace wmtk::tests { -// DEBUG_EdgeMesh::DEBUG_EdgeMesh(const EdgeMesh& m) -// : EdgeMesh(m) -// {} +DEBUG_EdgeMesh::DEBUG_EdgeMesh(const EdgeMesh& m) + : EdgeMesh(m) +{} DEBUG_EdgeMesh::DEBUG_EdgeMesh(EdgeMesh&& m) : EdgeMesh(std::move(m)) {} @@ -24,6 +24,8 @@ void DEBUG_EdgeMesh::print_state() const {} void DEBUG_EdgeMesh::print_ve() const { + throw("this function was written in the style of DEBUG_TriMesh::print_vf() but was not tested " + "yet"); auto ev_accessor = create_base_accessor(e_handle(PrimitiveType::Vertex)); auto e_flag_accessor = get_flag_accessor(PrimitiveType::Edge); for (long id = 0; id < capacity(PrimitiveType::Edge); ++id) { @@ -38,14 +40,15 @@ void DEBUG_EdgeMesh::print_ve() const Eigen::Matrix DEBUG_EdgeMesh::ev_from_eid(const long eid) const { + throw("this function is never used"); auto ev_accessor = create_base_accessor(e_handle(PrimitiveType::Vertex)); return ev_accessor.vector_attribute(eid); } auto DEBUG_EdgeMesh::edge_tuple_from_vids(const long v1, const long v2) const -> Tuple { + throw("this function is never used"); ConstAccessor ev = create_accessor(m_ev_handle); - auto ev_base = create_base_accessor(m_ev_handle); for (long eid = 0; eid < capacity(PrimitiveType::Edge); ++eid) { Tuple edge = edge_tuple_from_id(eid); auto ev0 = ev.const_vector_attribute(edge); From cf18878e70700f9f0c878c5109125c1d554c3e06 Mon Sep 17 00:00:00 2001 From: JcDai Date: Tue, 3 Oct 2023 17:19:51 -0400 Subject: [PATCH 40/49] add throw --- tests/tools/DEBUG_EdgeMesh.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/tools/DEBUG_EdgeMesh.cpp b/tests/tools/DEBUG_EdgeMesh.cpp index f626ca486b..e433c64d28 100644 --- a/tests/tools/DEBUG_EdgeMesh.cpp +++ b/tests/tools/DEBUG_EdgeMesh.cpp @@ -20,7 +20,10 @@ bool DEBUG_EdgeMesh::operator!=(const DEBUG_EdgeMesh& o) const return !(*this == o); } -void DEBUG_EdgeMesh::print_state() const {} +void DEBUG_EdgeMesh::print_state() const +{ + throw("This function is not implemented. maybe redundant"); +} void DEBUG_EdgeMesh::print_ve() const { From 56e6040c1bb0d2c4822d48475a5129767d4eb07b Mon Sep 17 00:00:00 2001 From: JcDai Date: Tue, 3 Oct 2023 17:27:55 -0400 Subject: [PATCH 41/49] redo changes in TriMesh --- src/wmtk/TriMesh.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wmtk/TriMesh.cpp b/src/wmtk/TriMesh.cpp index a57a8a40bf..99f709ad38 100644 --- a/src/wmtk/TriMesh.cpp +++ b/src/wmtk/TriMesh.cpp @@ -326,7 +326,7 @@ bool TriMesh::is_connectivity_valid() const cnt++; } } - if (cnt == 0) { + if (cnt != 1) { // std::cout << "EF and FE not compatible" << std::endl; return false; } @@ -345,7 +345,7 @@ bool TriMesh::is_connectivity_valid() const cnt++; } } - if (cnt == 0) { + if (cnt != 0) { // std::cout << "VF and FV not compatible" << std::endl; return false; } From d3cd444877ffadc29e0689f9f82f86abb2d153c4 Mon Sep 17 00:00:00 2001 From: JcDai Date: Tue, 3 Oct 2023 17:34:44 -0400 Subject: [PATCH 42/49] rollback the redo for Trimesh --- src/wmtk/TriMesh.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wmtk/TriMesh.cpp b/src/wmtk/TriMesh.cpp index 99f709ad38..a57a8a40bf 100644 --- a/src/wmtk/TriMesh.cpp +++ b/src/wmtk/TriMesh.cpp @@ -326,7 +326,7 @@ bool TriMesh::is_connectivity_valid() const cnt++; } } - if (cnt != 1) { + if (cnt == 0) { // std::cout << "EF and FE not compatible" << std::endl; return false; } @@ -345,7 +345,7 @@ bool TriMesh::is_connectivity_valid() const cnt++; } } - if (cnt != 0) { + if (cnt == 0) { // std::cout << "VF and FV not compatible" << std::endl; return false; } From 29a66749f059aef0488379d4d7c10ca1bc78ef92 Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Wed, 4 Oct 2023 12:13:06 -0400 Subject: [PATCH 43/49] refactor based on comments --- src/wmtk/EdgeMesh.cpp | 5 ++-- src/wmtk/EdgeMeshOperationExecutor.hpp | 4 +++ tests/test_tuple_1d.cpp | 35 +++++++++----------------- 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/wmtk/EdgeMesh.cpp b/src/wmtk/EdgeMesh.cpp index 5693ef0197..a3f39a3fa4 100644 --- a/src/wmtk/EdgeMesh.cpp +++ b/src/wmtk/EdgeMesh.cpp @@ -81,8 +81,9 @@ Tuple EdgeMesh::switch_tuple(const Tuple& tuple, PrimitiveType type) const // TODO: This is for special case self-loop, just to make sure the local vid of the returned // tuple is the same as the input. (When doing double-switch this is needed) - if (gcid_new == tuple.m_global_cid) return tuple; - + if (gcid_new == tuple.m_global_cid) { + return tuple; + } long lvid_new = -1; diff --git a/src/wmtk/EdgeMeshOperationExecutor.hpp b/src/wmtk/EdgeMeshOperationExecutor.hpp index 1bab89d288..a0dace515f 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.hpp +++ b/src/wmtk/EdgeMeshOperationExecutor.hpp @@ -21,6 +21,8 @@ class EdgeMesh::EdgeMeshOperationExecutor * @brief gather all simplices that are deleted in a split * * The deleted simplex is the edge itself + * @return std::array, 2> first vector contains the vertex ids, second vector + * contains the edge ids */ static const std::array, 2> get_split_simplices_to_delete( const Tuple& tuple, @@ -30,6 +32,8 @@ class EdgeMesh::EdgeMeshOperationExecutor * @brief gather all simplices that are deleted in a collapse * * The deleted simplices are the vertex and the edge of the input tuple + * @return std::array, 2> first vector contains the vertex ids, second vector + * contains the edge ids */ static const std::array, 2> get_collapse_simplices_to_delete( const Tuple& tuple, diff --git a/tests/test_tuple_1d.cpp b/tests/test_tuple_1d.cpp index cc1ed01bbd..e1488aeb59 100644 --- a/tests/test_tuple_1d.cpp +++ b/tests/test_tuple_1d.cpp @@ -109,12 +109,9 @@ TEST_CASE("1D_multiple_lines", "[tuple_generation], [tuple_1d]") { const std::vector vertices = m.get_all(PrimitiveType::Vertex); REQUIRE(vertices.size() == 6); - CHECK(m.id(vertices[0], PrimitiveType::Vertex) == 0); - CHECK(m.id(vertices[1], PrimitiveType::Vertex) == 1); - CHECK(m.id(vertices[2], PrimitiveType::Vertex) == 2); - CHECK(m.id(vertices[3], PrimitiveType::Vertex) == 3); - CHECK(m.id(vertices[4], PrimitiveType::Vertex) == 4); - CHECK(m.id(vertices[5], PrimitiveType::Vertex) == 5); + for (long i = 0; i < 6; ++i) { + CHECK(m.id(vertices[i], PrimitiveType::Vertex) == i); + } CHECK(m.id(vertices[0], PrimitiveType::Edge) == 0); CHECK(m.id(vertices[5], PrimitiveType::Edge) == 4); } @@ -122,11 +119,9 @@ TEST_CASE("1D_multiple_lines", "[tuple_generation], [tuple_1d]") { const std::vector edges = m.get_all(PrimitiveType::Edge); REQUIRE(edges.size() == 5); - CHECK(m.id(edges[0], PrimitiveType::Edge) == 0); - CHECK(m.id(edges[1], PrimitiveType::Edge) == 1); - CHECK(m.id(edges[2], PrimitiveType::Edge) == 2); - CHECK(m.id(edges[3], PrimitiveType::Edge) == 3); - CHECK(m.id(edges[4], PrimitiveType::Edge) == 4); + for (long i = 0; i < 5; ++i) { + CHECK(m.id(edges[i], PrimitiveType::Edge) == i); + } } } @@ -138,23 +133,17 @@ TEST_CASE("1D_loop_lines", "[tuple_generation], [tuple_1d]") { const std::vector vertices = m.get_all(PrimitiveType::Vertex); REQUIRE(vertices.size() == 6); - CHECK(m.id(vertices[0], PrimitiveType::Vertex) == 0); - CHECK(m.id(vertices[1], PrimitiveType::Vertex) == 1); - CHECK(m.id(vertices[2], PrimitiveType::Vertex) == 2); - CHECK(m.id(vertices[3], PrimitiveType::Vertex) == 3); - CHECK(m.id(vertices[4], PrimitiveType::Vertex) == 4); - CHECK(m.id(vertices[5], PrimitiveType::Vertex) == 5); + for (long i = 0; i < 6; ++i) { + CHECK(m.id(vertices[i], PrimitiveType::Vertex) == i); + } } SECTION("edges") { const std::vector edges = m.get_all(PrimitiveType::Edge); REQUIRE(edges.size() == 6); - CHECK(m.id(edges[0], PrimitiveType::Edge) == 0); - CHECK(m.id(edges[1], PrimitiveType::Edge) == 1); - CHECK(m.id(edges[2], PrimitiveType::Edge) == 2); - CHECK(m.id(edges[3], PrimitiveType::Edge) == 3); - CHECK(m.id(edges[4], PrimitiveType::Edge) == 4); - CHECK(m.id(edges[5], PrimitiveType::Edge) == 5); + for (long i = 0; i < 6; ++i) { + CHECK(m.id(edges[i], PrimitiveType::Edge) == i); + } } } From fd1197485763d43235d532f2a1b2fdd854072e18 Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Wed, 4 Oct 2023 12:17:15 -0400 Subject: [PATCH 44/49] reuse hash acc in tests --- tests/test_tuple_1d.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_tuple_1d.cpp b/tests/test_tuple_1d.cpp index e1488aeb59..263d0aa500 100644 --- a/tests/test_tuple_1d.cpp +++ b/tests/test_tuple_1d.cpp @@ -168,7 +168,7 @@ TEST_CASE("1D_self_loop", "[tuple_generation], [tuple_1d]") TEST_CASE("1D_random_switches", "[tuple_operation],[tuple_1d]") { DEBUG_EdgeMesh m = loop_lines(); - + ConstAccessor hash_accessor = m.get_const_cell_hash_accessor(); SECTION("vertices") { const std::vector vertex_tuples = m.get_all(PrimitiveType::Vertex); @@ -184,7 +184,7 @@ TEST_CASE("1D_random_switches", "[tuple_operation],[tuple_1d]") break; default: break; } - CHECK(m.is_valid_slow(t)); + CHECK(m.is_valid(t, hash_accessor)); } } } @@ -204,7 +204,7 @@ TEST_CASE("1D_random_switches", "[tuple_operation],[tuple_1d]") break; default: break; } - CHECK(m.is_valid_slow(t)); + CHECK(m.is_valid(t, hash_accessor)); } } } From 88f62a7acd4600ae21ad2d30401137a0cfdeee82 Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Wed, 4 Oct 2023 12:28:55 -0400 Subject: [PATCH 45/49] fix DEBUG_EdgeMesh::operator== --- tests/tools/DEBUG_EdgeMesh.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/tools/DEBUG_EdgeMesh.cpp b/tests/tools/DEBUG_EdgeMesh.cpp index e433c64d28..65ee274ee8 100644 --- a/tests/tools/DEBUG_EdgeMesh.cpp +++ b/tests/tools/DEBUG_EdgeMesh.cpp @@ -13,10 +13,12 @@ DEBUG_EdgeMesh::DEBUG_EdgeMesh(EdgeMesh&& m) bool DEBUG_EdgeMesh::operator==(const DEBUG_EdgeMesh& o) const { - return static_cast(*this) == static_cast(o); + throw("This function is not tested yet"); + return static_cast(*this) == static_cast(o); } bool DEBUG_EdgeMesh::operator!=(const DEBUG_EdgeMesh& o) const { + throw("This function is not tested yet"); return !(*this == o); } From 654099134c6a808434d2c2c6e71cd799176fd41f Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Mon, 9 Oct 2023 17:46:08 -0400 Subject: [PATCH 46/49] modify to fit the changes happend in main branch --- src/wmtk/EdgeMesh.hpp | 4 ++-- src/wmtk/EdgeMeshOperationExecutor.cpp | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/wmtk/EdgeMesh.hpp b/src/wmtk/EdgeMesh.hpp index 9784169d02..4bf35c37ff 100644 --- a/src/wmtk/EdgeMesh.hpp +++ b/src/wmtk/EdgeMesh.hpp @@ -18,9 +18,9 @@ class EdgeMesh : public Mesh PrimitiveType top_simplex_type() const override { return PrimitiveType::Edge; } - Tuple split_edge(const Tuple& t, Accessor& hash_accessor) override; + Tuple split_edge(const Tuple& t, Accessor& hash_accessor); - Tuple collapse_edge(const Tuple& t, Accessor& hash_accessor) override; + Tuple collapse_edge(const Tuple& t, Accessor& hash_accessor); Tuple switch_tuple(const Tuple& tuple, PrimitiveType type) const override; diff --git a/src/wmtk/EdgeMeshOperationExecutor.cpp b/src/wmtk/EdgeMeshOperationExecutor.cpp index 8ebf8e3e89..a1747e8354 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.cpp +++ b/src/wmtk/EdgeMeshOperationExecutor.cpp @@ -78,7 +78,9 @@ std::vector EdgeMesh::EdgeMeshOperationExecutor::prepare_operating_tuples { // this function is designed as a helper for multi_mesh throw("this function is not tested"); - return MultiMeshManager::map_edge_tuple_to_all_children(m_mesh, m_operating_tuple); + return m_mesh.m_multi_mesh_manager.map_edge_tuple_to_all_children( + m_mesh, + Simplex::edge(m_operating_tuple)); } Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge() From 3ee54bc80ecc11c11ef3ecd480a21622566caa1a Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Wed, 11 Oct 2023 13:16:42 -0400 Subject: [PATCH 47/49] typo in comment --- src/wmtk/MultiMeshManager.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/wmtk/MultiMeshManager.hpp b/src/wmtk/MultiMeshManager.hpp index 7e380bc88f..d5efb446a0 100644 --- a/src/wmtk/MultiMeshManager.hpp +++ b/src/wmtk/MultiMeshManager.hpp @@ -54,7 +54,7 @@ class MultiMeshManager // Map functions //=========== //=========== - // Note that when we map a M-tuplefrom a K-complex to a J-complex there are different + // Note that when we map a M-tuple from a K-complex to a J-complex there are different // relationships necessary if K == J // if M == K then this is unique // if M < K then this is many to many @@ -62,7 +62,8 @@ class MultiMeshManager // if M == K then it is one to many // if M < K then it is many to many // - // Note also that functions that end with _tuple or _tuples willl return tuples rather than simplices + // Note also that functions that end with _tuple or _tuples willl return tuples rather than + // simplices //=========== // Simplex maps @@ -138,8 +139,6 @@ class MultiMeshManager map_to_child_tuples(const Mesh& my_mesh, long child_id, const Simplex& simplex) const; - - static Tuple map_tuple_between_meshes( const Mesh& source_mesh, const Mesh& target_mesh, From 25251ca9330595a6e90b3dc93baeb3736cffcc75 Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Wed, 11 Oct 2023 19:22:38 -0400 Subject: [PATCH 48/49] fix compile --- src/wmtk/EdgeMeshOperationExecutor.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/wmtk/EdgeMeshOperationExecutor.cpp b/src/wmtk/EdgeMeshOperationExecutor.cpp index a1747e8354..abdc4ee307 100644 --- a/src/wmtk/EdgeMeshOperationExecutor.cpp +++ b/src/wmtk/EdgeMeshOperationExecutor.cpp @@ -77,10 +77,11 @@ std::vector EdgeMesh::EdgeMeshOperationExecutor::prepare_operating_tuples const { // this function is designed as a helper for multi_mesh - throw("this function is not tested"); - return m_mesh.m_multi_mesh_manager.map_edge_tuple_to_all_children( - m_mesh, - Simplex::edge(m_operating_tuple)); + throw("this function is not implemented"); + // return m_mesh.m_multi_mesh_manager.map_edge_tuple_to_all_children( + // m_mesh, + // Simplex::edge(m_operating_tuple)); + return std::vector(); } Tuple EdgeMesh::EdgeMeshOperationExecutor::split_edge() From e991d24ee545c42cddda2f5cca006d52afee3e33 Mon Sep 17 00:00:00 2001 From: zlyfunction Date: Wed, 11 Oct 2023 19:25:23 -0400 Subject: [PATCH 49/49] delete TODO in comments --- src/wmtk/EdgeMesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wmtk/EdgeMesh.cpp b/src/wmtk/EdgeMesh.cpp index a3f39a3fa4..8ee61b4184 100644 --- a/src/wmtk/EdgeMesh.cpp +++ b/src/wmtk/EdgeMesh.cpp @@ -79,7 +79,7 @@ Tuple EdgeMesh::switch_tuple(const Tuple& tuple, PrimitiveType type) const long gcid_new = ee(tuple.m_local_vid); - // TODO: This is for special case self-loop, just to make sure the local vid of the returned + // This is for special case self-loop, just to make sure the local vid of the returned // tuple is the same as the input. (When doing double-switch this is needed) if (gcid_new == tuple.m_global_cid) { return tuple;