diff --git a/components/wmtk_components/CMakeLists.txt b/components/wmtk_components/CMakeLists.txt index 549bd35084..793a6e97c6 100644 --- a/components/wmtk_components/CMakeLists.txt +++ b/components/wmtk_components/CMakeLists.txt @@ -1,4 +1,4 @@ - +add_subdirectory(delaunay) add_subdirectory(input) add_subdirectory(isotropic_remeshing) add_subdirectory(mesh_info) diff --git a/components/wmtk_components/delaunay/CMakeLists.txt b/components/wmtk_components/delaunay/CMakeLists.txt new file mode 100644 index 0000000000..ff82b6117a --- /dev/null +++ b/components/wmtk_components/delaunay/CMakeLists.txt @@ -0,0 +1,13 @@ + +set(SRC_FILES + internal/DelaunayOptions.hpp + internal/delaunay_2d.hpp + internal/delaunay_2d.cpp + internal/delaunay_3d.hpp + internal/delaunay_3d.cpp + internal/delaunay_geogram.hpp + internal/delaunay_geogram.cpp + delaunay.hpp + delaunay.cpp + ) +target_sources(wildmeshing_components PRIVATE ${SRC_FILES}) diff --git a/components/wmtk_components/delaunay/delaunay.cpp b/components/wmtk_components/delaunay/delaunay.cpp new file mode 100644 index 0000000000..c9e3d668fe --- /dev/null +++ b/components/wmtk_components/delaunay/delaunay.cpp @@ -0,0 +1,114 @@ +#include "delaunay.hpp" + +#include +#include +#include +#include +#include +#include + +#include "internal/DelaunayOptions.hpp" +#include "internal/delaunay_2d.hpp" +#include "internal/delaunay_3d.hpp" + +namespace wmtk { +namespace components { + +template +RowVectors points_to_rowvectors(PointMesh& point_cloud) +{ + auto pts_attr = point_cloud.get_attribute_handle("position", PrimitiveType::Vertex); + auto pts_acc = point_cloud.create_accessor(pts_attr); + + const auto vertices = point_cloud.get_all(PrimitiveType::Vertex); + + RowVectors vec(vertices.size(), D); + size_t i = 0; + for (const Tuple& t : vertices) { + const auto p = pts_acc.vector_attribute(t); + vec.row(i) = p.transpose(); + ++i; + } + + return vec; +} + +template +void delaunay_exec( + const internal::DelaunayOptions& options, + std::map& files) +{ + // 2d --> TriMesh + // 3d --> TetMesh + static_assert( + (D == 2 && std::is_same()) || (D == 3 && std::is_same())); + + // input + PointMesh point_cloud; + { + const std::filesystem::path& file = files[options.input]; + MeshReader reader(file); + reader.read(point_cloud); + } + + // make sure dimensions fit + { + auto pts_attr = point_cloud.get_attribute_handle("position", PrimitiveType::Vertex); + auto pts_acc = point_cloud.create_accessor(pts_attr); + assert(pts_acc.dimension() == options.cell_dimension); + } + + if constexpr (D == 2) { + throw "not tested for 2d"; + } + + MeshT mesh; + Eigen::MatrixXd vertices; + Eigen::MatrixXi faces; + const auto pts_vec = points_to_rowvectors(point_cloud); + if constexpr (D == 2) { + std::tie(vertices, faces) = internal::delaunay_2d(pts_vec); + } else if constexpr (D == 3) { + std::tie(vertices, faces) = internal::delaunay_3d(pts_vec); + } else { + throw "unsupported cell dimension in delaunay component"; + } + + mesh.initialize(faces.cast()); + mesh_utils::set_matrix_attribute(vertices, "position", PrimitiveType::Vertex, mesh); + + // output + { + const std::filesystem::path cache_dir = "cache"; + const std::filesystem::path cached_mesh_file = cache_dir / (options.output + ".hdf5"); + + HDF5Writer writer(cached_mesh_file); + mesh.serialize(writer); + + files[options.output] = cached_mesh_file; + } +} + +void delaunay(const nlohmann::json& j, std::map& files) +{ + using namespace internal; + + DelaunayOptions options = j.get(); + + // delaunay + switch (options.cell_dimension) { + case 2: { + delaunay_exec<2, TriMesh>(options, files); + break; + } + case 3: { + delaunay_exec<3, TetMesh>(options, files); + break; + } + default: { + throw "unsupported cell dimension in delaunay component"; + } + } +} +} // namespace components +} // namespace wmtk diff --git a/components/wmtk_components/delaunay/delaunay.hpp b/components/wmtk_components/delaunay/delaunay.hpp new file mode 100644 index 0000000000..3aaa841144 --- /dev/null +++ b/components/wmtk_components/delaunay/delaunay.hpp @@ -0,0 +1,9 @@ +#pragma once +#include +#include + +namespace wmtk::components { + +void delaunay(const nlohmann::json& j, std::map& files); + +} // namespace wmtk::components diff --git a/components/wmtk_components/delaunay/internal/DelaunayOptions.hpp b/components/wmtk_components/delaunay/internal/DelaunayOptions.hpp new file mode 100644 index 0000000000..b860d5b4d7 --- /dev/null +++ b/components/wmtk_components/delaunay/internal/DelaunayOptions.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +namespace wmtk { +namespace components { +namespace internal { + +struct DelaunayOptions +{ + std::string type; + std::string input; + std::string output; + long cell_dimension = -1; +}; + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(DelaunayOptions, type, input, output, cell_dimension); + +} // namespace internal +} // namespace components +} // namespace wmtk \ No newline at end of file diff --git a/components/wmtk_components/delaunay/internal/delaunay_2d.cpp b/components/wmtk_components/delaunay/internal/delaunay_2d.cpp new file mode 100644 index 0000000000..34f13833a6 --- /dev/null +++ b/components/wmtk_components/delaunay/internal/delaunay_2d.cpp @@ -0,0 +1,13 @@ +#include "delaunay_2d.hpp" +#include +#include "delaunay_geogram.hpp" + + +namespace wmtk::components::internal { + +std::tuple delaunay_2d(Eigen::Ref points) +{ + return delaunay_geogram(points); +} + +} // namespace wmtk::components::internal diff --git a/components/wmtk_components/delaunay/internal/delaunay_2d.hpp b/components/wmtk_components/delaunay/internal/delaunay_2d.hpp new file mode 100644 index 0000000000..bee2aff63a --- /dev/null +++ b/components/wmtk_components/delaunay/internal/delaunay_2d.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include + +namespace wmtk::components::internal { +std::tuple delaunay_2d(Eigen::Ref points); +} // namespace wmtk::components::internal diff --git a/components/wmtk_components/delaunay/internal/delaunay_3d.cpp b/components/wmtk_components/delaunay/internal/delaunay_3d.cpp new file mode 100644 index 0000000000..f3662b4842 --- /dev/null +++ b/components/wmtk_components/delaunay/internal/delaunay_3d.cpp @@ -0,0 +1,12 @@ +#include "delaunay_3d.hpp" +#include "delaunay_geogram.hpp" + + +namespace wmtk::components::internal { + +std::tuple delaunay_3d(Eigen::Ref points) +{ + return delaunay_geogram(points); +} + +} // namespace wmtk::components::internal diff --git a/components/wmtk_components/delaunay/internal/delaunay_3d.hpp b/components/wmtk_components/delaunay/internal/delaunay_3d.hpp new file mode 100644 index 0000000000..365720ca1f --- /dev/null +++ b/components/wmtk_components/delaunay/internal/delaunay_3d.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include + +namespace wmtk::components::internal { +std::tuple delaunay_3d(Eigen::Ref points); +} // namespace wmtk::components::internal diff --git a/components/wmtk_components/delaunay/internal/delaunay_geogram.cpp b/components/wmtk_components/delaunay/internal/delaunay_geogram.cpp new file mode 100644 index 0000000000..d97f30cee4 --- /dev/null +++ b/components/wmtk_components/delaunay/internal/delaunay_geogram.cpp @@ -0,0 +1,89 @@ +#include "delaunay_geogram.hpp" + +#include +#include +#include + +#include + +namespace wmtk::components::internal { + +std::tuple delaunay_geogram( + Eigen::Ref points) +{ + Eigen::MatrixXd vertices; + Eigen::MatrixXi tetrahedra; + + if (points.rows() == 0) { + wmtk::logger().warn("Cannot run delaunay on an empty point set"); + return {vertices, tetrahedra}; + } + + long dim = points.cols(); + assert(dim == 2 || dim == 3); + + static std::once_flag once_flag; + std::call_once(once_flag, []() { GEO::initialize(); }); + + GEO::Delaunay_var engine; + switch (dim) { + case 2: { + engine = GEO::Delaunay::create(2, "BDEL2d"); + break; + } + case 3: { + engine = GEO::Delaunay::create(3, "BDEL"); + break; + } + default: throw "unexpected vector type in delaunay_geogram"; + } + + assert(engine); + + // Some settings + engine->set_reorder(false); + engine->set_stores_cicl(false); // Incident tetrahedral list. + engine->set_stores_neighbors(false); // Vertex neighbors. + engine->set_refine(false); + engine->set_keeps_infinite(false); + + // Run! + geo_assert(points.size() > 0); + Eigen::MatrixXd points_transposed = points.transpose(); + engine->set_vertices(static_cast(points.rows()), points_transposed.data()); + + // Extract output. + vertices.resize(engine->nb_vertices(), dim); + tetrahedra.resize(engine->nb_cells(), dim + 1); + + for (GEO::index_t i = 0; i < vertices.rows(); ++i) { + // depending on branch prediction to make these calls cost nothing + switch (dim) { + case 2: { + vertices.row(i) = Eigen::Map(engine->vertex_ptr(i)).transpose(); + break; + } + case 3: { + vertices.row(i) = Eigen::Map(engine->vertex_ptr(i)).transpose(); + break; + } + default: { + // for generality allowing for arbitrary dimensions + vertices.row(i) = + Eigen::Map(engine->vertex_ptr(i), dim).transpose(); + break; + } + } + } + + for (GEO::index_t i = 0; i < tetrahedra.rows(); ++i) { + for (GEO::index_t j = 0; j < tetrahedra.cols(); ++j) { + tetrahedra(i, j) = engine->cell_vertex(i, j); + } + } + + return {vertices, tetrahedra}; +} + + +} // namespace wmtk::components::internal \ No newline at end of file diff --git a/components/wmtk_components/delaunay/internal/delaunay_geogram.hpp b/components/wmtk_components/delaunay/internal/delaunay_geogram.hpp new file mode 100644 index 0000000000..9570dc4696 --- /dev/null +++ b/components/wmtk_components/delaunay/internal/delaunay_geogram.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace wmtk::components::internal { + +std::tuple delaunay_geogram( + Eigen::Ref points); +} // namespace wmtk::components::internal \ No newline at end of file diff --git a/components/wmtk_components/input/input.cpp b/components/wmtk_components/input/input.cpp index 7a3b346627..449da196ed 100644 --- a/components/wmtk_components/input/input.cpp +++ b/components/wmtk_components/input/input.cpp @@ -1,6 +1,7 @@ #include "input.hpp" #include +#include #include #include #include @@ -20,32 +21,78 @@ void input(const nlohmann::json& j, std::map throw std::runtime_error(std::string("file") + options.file.string() + " not found"); } - TriMesh mesh; - if (options.file.extension() == ".hdf5") { - MeshReader reader(options.file); - reader.read(mesh); - } else if (options.file.extension() == ".off" || options.file.extension() == ".obj") { - Eigen::MatrixXd V; - Eigen::Matrix F; - igl::read_triangle_mesh(options.file.string(), V, F); + switch (options.cell_dimension) { + case 0: { + // point-cloud + PointMesh mesh; + if (options.file.extension() == ".hdf5") { + MeshReader reader(options.file); + reader.read(mesh); + } else if (options.file.extension() == ".off" || options.file.extension() == ".obj") { + Eigen::MatrixXd V; + Eigen::Matrix F; + igl::read_triangle_mesh(options.file.string(), V, F); - mesh.initialize(F); + mesh.initialize(V.rows()); - mesh_utils::set_matrix_attribute(V, "position", PrimitiveType::Vertex, mesh); + mesh_utils::set_matrix_attribute(V, "position", PrimitiveType::Vertex, mesh); - } else { - throw std::runtime_error(std::string("Unknown file type: ") + options.file.string()); + } else { + throw std::runtime_error(std::string("Unknown file type: ") + options.file.string()); + } + + const std::filesystem::path cache_dir = "cache"; + std::filesystem::create_directory(cache_dir); + + const std::filesystem::path cached_mesh_file = cache_dir / (options.name + ".hdf5"); + + HDF5Writer writer(cached_mesh_file); + mesh.serialize(writer); + + files[options.name] = cached_mesh_file; + break; } + case 1: + // edge mesh + throw "not implemented"; + assert(false); + break; + case 2: { + // triangle mesh + TriMesh mesh; + if (options.file.extension() == ".hdf5") { + MeshReader reader(options.file); + reader.read(mesh); + } else if (options.file.extension() == ".off" || options.file.extension() == ".obj") { + Eigen::MatrixXd V; + Eigen::Matrix F; + igl::read_triangle_mesh(options.file.string(), V, F); + + mesh.initialize(F); - const std::filesystem::path cache_dir = "cache"; - std::filesystem::create_directory(cache_dir); + mesh_utils::set_matrix_attribute(V, "position", PrimitiveType::Vertex, mesh); - const std::filesystem::path cached_mesh_file = cache_dir / (options.name + ".hdf5"); + } else { + throw std::runtime_error(std::string("Unknown file type: ") + options.file.string()); + } - HDF5Writer writer(cached_mesh_file); - mesh.serialize(writer); + const std::filesystem::path cache_dir = "cache"; + std::filesystem::create_directory(cache_dir); - files[options.name] = cached_mesh_file; + const std::filesystem::path cached_mesh_file = cache_dir / (options.name + ".hdf5"); + + HDF5Writer writer(cached_mesh_file); + mesh.serialize(writer); + + files[options.name] = cached_mesh_file; + break; + } + case 3: + // tetrahedra mesh + assert(false); + break; + default: assert(false); break; + } } } // namespace components } // namespace wmtk \ No newline at end of file diff --git a/components/wmtk_components/input/internal/InputOptions.hpp b/components/wmtk_components/input/internal/InputOptions.hpp index a8e399c5b6..72cc44bafe 100644 --- a/components/wmtk_components/input/internal/InputOptions.hpp +++ b/components/wmtk_components/input/internal/InputOptions.hpp @@ -12,9 +12,10 @@ struct InputOptions std::string type; std::string name; std::filesystem::path file; + long cell_dimension = -1; }; -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(InputOptions, type, name, file); +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(InputOptions, type, name, file, cell_dimension); } // namespace internal } // namespace components diff --git a/components/wmtk_components/output/internal/OutputOptions.hpp b/components/wmtk_components/output/internal/OutputOptions.hpp index 88ee4f17cf..9fee32fe7d 100644 --- a/components/wmtk_components/output/internal/OutputOptions.hpp +++ b/components/wmtk_components/output/internal/OutputOptions.hpp @@ -11,10 +11,11 @@ struct OutputOptions { std::string type; std::string input; + long cell_dimension = -1; std::filesystem::path file; }; -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(OutputOptions, type, input, file); +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(OutputOptions, type, input, cell_dimension, file); } // namespace internal } // namespace components diff --git a/components/wmtk_components/output/output.cpp b/components/wmtk_components/output/output.cpp index 0a96d3efab..42445fa5cc 100644 --- a/components/wmtk_components/output/output.cpp +++ b/components/wmtk_components/output/output.cpp @@ -1,6 +1,7 @@ #include "output.hpp" #include +#include #include #include #include @@ -16,23 +17,45 @@ void output(const nlohmann::json& j, std::map(); + switch (options.cell_dimension) { + case 2: { + TriMesh mesh; + { + const std::filesystem::path& file = files[options.input]; + MeshReader reader(file); + reader.read(mesh); + } - TriMesh mesh; - { - const std::filesystem::path& file = files[options.input]; - MeshReader reader(file); - reader.read(mesh); + if (options.file.extension().empty()) { + ParaviewWriter writer(options.file, "position", mesh, true, true, true, false); + mesh.serialize(writer); + } else if (options.file.extension() == ".off" || options.file.extension() == ".obj") { + throw "not implemented yet"; + } else { + throw std::runtime_error(std::string("Unknown file type: ") + options.file.string()); + } + break; } + case 3: { + TetMesh mesh; + { + const std::filesystem::path& file = files[options.input]; + MeshReader reader(file); + reader.read(mesh); + } - if (options.file.extension().empty()) { - // HDF5Writer writer(options.file); - // mesh.serialize(writer); - ParaviewWriter writer(options.file, "position", mesh, true, true, true, false); - mesh.serialize(writer); - } else if (options.file.extension() == ".off" || options.file.extension() == ".obj") { - throw "not implemented yet"; - } else { - throw std::runtime_error(std::string("Unknown file type: ") + options.file.string()); + if (options.file.extension().empty()) { + ParaviewWriter writer(options.file, "position", mesh, true, true, true, true); + mesh.serialize(writer); + } else { + throw std::runtime_error(std::string("Unknown file type: ") + options.file.string()); + } + break; + } + default: { + throw "output component cannot process the given cell dimension"; + break; + } } } } // namespace components diff --git a/scripts/2d_switch_tables.ipynb b/scripts/2d_switch_tables.ipynb index a60bf59865..81116cceb8 100644 --- a/scripts/2d_switch_tables.ipynb +++ b/scripts/2d_switch_tables.ipynb @@ -2,7 +2,16 @@ "cells": [ { "cell_type": "code", - "execution_count": 14, + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from autogenerate import autogenerate" + ] + }, + { + "cell_type": "code", + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -11,7 +20,7 @@ "3" ] }, - "execution_count": 14, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } @@ -40,7 +49,7 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -64,7 +73,7 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -85,7 +94,7 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -121,12 +130,12 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# Builds a table for the switch operation of dimension d\n", - "def table(d,name,s):\n", + "def table(d,s):\n", " # Generates a table for switch_vertex\n", " sv = all_tuples(s)\n", "\n", @@ -136,53 +145,42 @@ " else:\n", " sv[i] = switch(sv[i],d,s)\n", "\n", - " return list_to_array(sv,name)" + " return sv" ] }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 7, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'static long auto_2d_table_ccw[9][1] = {\\n {-1},\\n {0},\\n {1},\\n {1},\\n {-1},\\n {0},\\n {0},\\n {1},\\n {-1}\\n};\\n'" - ] - }, - "execution_count": 47, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# Builds a table for the switch operation of dimension d\n", - "def table_ccw(name,s):\n", + "def table_ccw(s):\n", " # Generates a table for switch_vertex\n", " sv = all_tuples(s)\n", " out = [-1 for i in sv]\n", "\n", " for i in range(len(sv)):\n", " if not valid_tuple(sv[i],s):\n", - " out[i] = [-1]\n", + " out[i] = -1\n", " else:\n", " if ccw_tuple(sv[i],s):\n", - " out[i] = [1]\n", + " out[i] = 1\n", " else:\n", - " out[i] = [0]\n", + " out[i] = 0\n", " \n", - " return list_to_array(out,name)\n", + " return out\n", "\n", "# table_ccw(\"auto_2d_table_ccw\",s)" ] }, { "cell_type": "code", - "execution_count": 61, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ - "def table_complete_tuple(name,d,s):\n", + "def table_complete_tuple(d,s):\n", " # Generates a table for switch_vertex\n", " sv = [t for t in all_tuples(s) if (valid_tuple(t,s) and ccw_tuple(t,s))]\n", " out = []\n", @@ -194,50 +192,61 @@ " \n", " assert(len(out) == len(s[d]))\n", " \n", - " return list_to_array(out,name)\n", + " return out\n", "\n", "#table_complete_tuple(\"complete_vertex\",0,s)\n" ] }, { "cell_type": "code", - "execution_count": 62, + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ - "text_file = open(\"../src/wmtk/autogen/autogenerated_2d_tables.hpp\", \"w\")\n", - "text_file.write('// Autogenerated by 2d_switch_tables.ipynb\\n\\n')\n", - "text_file.write('namespace wmtk { namespace autogen {\\n')\n", - "text_file.write(list_to_array(edges,\"auto_2d_edges\"))\n", - "text_file.write(table(0,\"auto_2d_table_vertex\",s))\n", - "text_file.write(table(1,\"auto_2d_table_edge\",s))\n", - "text_file.write(table_ccw(\"auto_2d_table_ccw\",s))\n", - "text_file.write(table_complete_tuple(\"auto_2d_table_complete_vertex\",0,s))\n", - "text_file.write(table_complete_tuple(\"auto_2d_table_complete_edge\",1,s))\n", - "\n", - "text_file.write(\"}}\\n\")\n", - "\n", - "text_file.close()" + "def list_pair_to_array(lists, name, comment = None):\n", + " r = {\"name\": name, \"data\": lists}\n", + " if comment is not None: r[\"comment\"] = comment\n", + " return r" ] }, { "cell_type": "code", - "execution_count": 49, + "execution_count": 10, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]" - ] - }, - "execution_count": 49, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], + "source": [ + "tri_data = {\"namespace\": \"tri_mesh\", \"tables\": [\n", + "list_pair_to_array(edges,\"auto_2d_edges\", \"lvids for a particular leid\"),\n", + "list_pair_to_array(table(0,s),\"auto_2d_table_vertex\", \"vertex switch's (tuple_index -> [lvid,leid])\"),\n", + "list_pair_to_array(table(1,s),\"auto_2d_table_edge\", \"edge switch's (tuple_index -> [lvid,leid])\"),\n", + "list_pair_to_array(table_ccw(s),\"auto_2d_table_ccw\", \"(tuple_index) -> is_ccw\"),\n", + "list_pair_to_array(table_complete_tuple(0,s),\"auto_2d_table_complete_vertex\", \"lvid -> a ccw [lvid,leid]\"),\n", + "list_pair_to_array(table_complete_tuple(1,s),\"auto_2d_table_complete_edge\", \"leid -> a ccw [lvid,leid]\")]}\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [] }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "autogenerate(\"../src/wmtk/autogen/tri_mesh/autogenerated_tables.{}pp\", tri_data)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -248,7 +257,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -262,9 +271,8 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.6" - }, - "orig_nbformat": 4 + "version": "3.10.12" + } }, "nbformat": 4, "nbformat_minor": 2 diff --git a/scripts/3d_switch_tables.ipynb b/scripts/3d_switch_tables.ipynb index 69a157c2aa..79a16118d2 100644 --- a/scripts/3d_switch_tables.ipynb +++ b/scripts/3d_switch_tables.ipynb @@ -2,7 +2,16 @@ "cells": [ { "cell_type": "code", - "execution_count": 21, + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from autogenerate import autogenerate" + ] + }, + { + "cell_type": "code", + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -11,7 +20,7 @@ "4" ] }, - "execution_count": 21, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } @@ -52,7 +61,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -81,7 +90,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -102,7 +111,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -138,12 +147,12 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# Builds a table for the switch operation of dimension d\n", - "def table(d,name,s):\n", + "def table(d,s):\n", " # Generates a table for switch_vertex\n", " sv = all_tuples(s)\n", "\n", @@ -153,42 +162,42 @@ " else:\n", " sv[i] = switch(sv[i],d,s)\n", "\n", - " return list_to_array(sv,name)" + " return sv" ] }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "# Builds a table for the switch operation of dimension d\n", - "def table_ccw(name,s):\n", + "def table_ccw(s):\n", " # Generates a table for switch_vertex\n", " sv = all_tuples(s)\n", " out = [-1 for i in sv]\n", "\n", " for i in range(len(sv)):\n", " if not valid_tuple(sv[i],s):\n", - " out[i] = [-1]\n", + " out[i] = -1\n", " else:\n", " if ccw_tuple(sv[i],s):\n", - " out[i] = [1]\n", + " out[i] = 1\n", " else:\n", - " out[i] = [0]\n", + " out[i] = 0\n", " \n", - " return list_to_array(out,name)\n", + " return out\n", "\n", "# table_ccw(\"auto_3d_table_ccw\",s)" ] }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ - "def table_complete_tuple(name,d,s):\n", + "def table_complete_tuple(d,s):\n", " # Generates a table for switch_vertex\n", " sv = [t for t in all_tuples(s) if (valid_tuple(t,s) and ccw_tuple(t,s))]\n", " out = []\n", @@ -200,31 +209,480 @@ " \n", " assert(len(out) == len(s[d]))\n", " \n", - " return list_to_array(out,name)\n" + " return out\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "def list_pair_to_array(lists, name, comment = None):\n", + " r = {\"name\": name, \"data\": lists}\n", + " if comment is not None: r[\"comment\"] = comment\n", + " return r" ] }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ - "text_file = open(\"../src/wmtk/autogen/autogenerated_3d_tables.hpp\", \"w\")\n", - "text_file.write('// Autogenerated by 3d_switch_tables.ipynb\\n\\n')\n", - "text_file.write('namespace wmtk { namespace autogen {\\n')\n", - "text_file.write(list_to_array(edges,\"auto_3d_edges\"))\n", - "text_file.write(list_to_array(faces,\"auto_3d_faces\"))\n", - "text_file.write(table(0,\"auto_3d_table_vertex\",s))\n", - "text_file.write(table(1,\"auto_3d_table_edge\",s))\n", - "text_file.write(table(2,\"auto_3d_table_face\",s))\n", - "text_file.write(table_ccw(\"auto_3d_table_ccw\",s))\n", - "text_file.write(table_complete_tuple(\"auto_3d_table_complete_vertex\",0,s))\n", - "text_file.write(table_complete_tuple(\"auto_3d_table_complete_edge\",1,s))\n", - "text_file.write(table_complete_tuple(\"auto_3d_table_complete_face\",2,s))\n", - "\n", - "text_file.write(\"}}\")\n", - "\n", - "text_file.close()" + "tet_data = {\"namespace\": \"tet_mesh\", \"tables\": [\n", + "list_pair_to_array(edges,\"auto_3d_edges\", \"lvids for a specfic leid\"),\n", + "list_pair_to_array(faces,\"auto_3d_faces\", \"lvids for a specific lfid\"),\n", + "list_pair_to_array(table(0,s),\"auto_3d_table_vertex\", \"vertex switch's (tuple_index -> [lvid,leid,lfid])\"),\n", + "list_pair_to_array(table(1,s),\"auto_3d_table_edge\", \"edge switch's (tuple_index -> [lvid,leid,lfid])\"),\n", + "list_pair_to_array(table(2,s),\"auto_3d_table_face\", \"face switch's (tuple_index -> [lvid,leid,lfid])\"),\n", + "list_pair_to_array(table_ccw(s),\"auto_3d_table_ccw\", \"(tuple_index) -> is_ccw\"),\n", + "list_pair_to_array(table_complete_tuple(0,s),\"auto_3d_table_complete_vertex\", \"lvid -> a ccw [lvid,leid,lfid]\"),\n", + "list_pair_to_array(table_complete_tuple(1,s),\"auto_3d_table_complete_edge\", \"evid -> a ccw [lvid,leid,lfid]\"),\n", + "list_pair_to_array(table_complete_tuple(2,s),\"auto_3d_table_complete_face\", \"fvid -> a ccw [lvid,leid,lfid]\")]}" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'namespace': 'tet_mesh',\n", + " 'tables': [{'name': 'auto_3d_edges',\n", + " 'data': [{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}],\n", + " 'comment': 'lvids for a specfic leid'},\n", + " {'name': 'auto_3d_faces',\n", + " 'data': [{1, 2, 3}, {0, 2, 3}, {0, 1, 3}, {0, 1, 2}],\n", + " 'comment': 'lvids for a specific lfid'},\n", + " {'name': 'auto_3d_table_vertex',\n", + " 'data': [[-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [1, 0, 2],\n", + " [1, 0, 3],\n", + " [-1, -1, -1],\n", + " [2, 1, 1],\n", + " [-1, -1, -1],\n", + " [2, 1, 3],\n", + " [-1, -1, -1],\n", + " [3, 2, 1],\n", + " [3, 2, 2],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [0, 0, 2],\n", + " [0, 0, 3],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [2, 3, 0],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [2, 3, 3],\n", + " [3, 4, 0],\n", + " [-1, -1, -1],\n", + " [3, 4, 2],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [0, 1, 1],\n", + " [-1, -1, -1],\n", + " [0, 1, 3],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [1, 3, 0],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [1, 3, 3],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [3, 5, 0],\n", + " [3, 5, 1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [0, 2, 1],\n", + " [0, 2, 2],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [1, 4, 0],\n", + " [-1, -1, -1],\n", + " [1, 4, 2],\n", + " [-1, -1, -1],\n", + " [2, 5, 0],\n", + " [2, 5, 1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1]],\n", + " 'comment': \"vertex switch's (tuple_index -> [lvid,leid,lfid])\"},\n", + " {'name': 'auto_3d_table_edge',\n", + " 'data': [[-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [0, 2, 2],\n", + " [0, 1, 3],\n", + " [-1, -1, -1],\n", + " [0, 2, 1],\n", + " [-1, -1, -1],\n", + " [0, 0, 3],\n", + " [-1, -1, -1],\n", + " [0, 1, 1],\n", + " [0, 0, 2],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [1, 4, 2],\n", + " [1, 3, 3],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [1, 4, 0],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [1, 0, 3],\n", + " [1, 3, 0],\n", + " [-1, -1, -1],\n", + " [1, 0, 2],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [2, 5, 1],\n", + " [-1, -1, -1],\n", + " [2, 3, 3],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [2, 5, 0],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [2, 1, 3],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [2, 3, 0],\n", + " [2, 1, 1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [3, 5, 1],\n", + " [3, 4, 2],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [3, 5, 0],\n", + " [-1, -1, -1],\n", + " [3, 2, 2],\n", + " [-1, -1, -1],\n", + " [3, 4, 0],\n", + " [3, 2, 1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1]],\n", + " 'comment': \"edge switch's (tuple_index -> [lvid,leid,lfid])\"},\n", + " {'name': 'auto_3d_table_face',\n", + " 'data': [[-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [0, 0, 3],\n", + " [0, 0, 2],\n", + " [-1, -1, -1],\n", + " [0, 1, 3],\n", + " [-1, -1, -1],\n", + " [0, 1, 1],\n", + " [-1, -1, -1],\n", + " [0, 2, 2],\n", + " [0, 2, 1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [1, 0, 3],\n", + " [1, 0, 2],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [1, 3, 3],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [1, 3, 0],\n", + " [1, 4, 2],\n", + " [-1, -1, -1],\n", + " [1, 4, 0],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [2, 1, 3],\n", + " [-1, -1, -1],\n", + " [2, 1, 1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [2, 3, 3],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [2, 3, 0],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [2, 5, 1],\n", + " [2, 5, 0],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [3, 2, 2],\n", + " [3, 2, 1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1],\n", + " [3, 4, 2],\n", + " [-1, -1, -1],\n", + " [3, 4, 0],\n", + " [-1, -1, -1],\n", + " [3, 5, 1],\n", + " [3, 5, 0],\n", + " [-1, -1, -1],\n", + " [-1, -1, -1]],\n", + " 'comment': \"face switch's (tuple_index -> [lvid,leid,lfid])\"},\n", + " {'name': 'auto_3d_table_ccw',\n", + " 'data': [-1,\n", + " -1,\n", + " 1,\n", + " 0,\n", + " -1,\n", + " 0,\n", + " -1,\n", + " 1,\n", + " -1,\n", + " 1,\n", + " 0,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " 0,\n", + " 1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " 1,\n", + " -1,\n", + " -1,\n", + " 0,\n", + " 0,\n", + " -1,\n", + " 1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " 1,\n", + " -1,\n", + " 0,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " 0,\n", + " -1,\n", + " -1,\n", + " 1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " 1,\n", + " 0,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " 0,\n", + " 1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " -1,\n", + " 1,\n", + " -1,\n", + " 0,\n", + " -1,\n", + " 0,\n", + " 1,\n", + " -1,\n", + " -1],\n", + " 'comment': '(tuple_index) -> is_ccw'},\n", + " {'name': 'auto_3d_table_complete_vertex',\n", + " 'data': [[0, 0, 2], [1, 0, 3], [2, 1, 1], [3, 2, 2]],\n", + " 'comment': 'lvid -> a ccw [lvid,leid,lfid]'},\n", + " {'name': 'auto_3d_table_complete_edge',\n", + " 'data': [[0, 0, 2], [0, 1, 3], [0, 2, 1], [1, 3, 0], [1, 4, 2], [2, 5, 0]],\n", + " 'comment': 'evid -> a ccw [lvid,leid,lfid]'},\n", + " {'name': 'auto_3d_table_complete_face',\n", + " 'data': [[1, 3, 0], [0, 2, 1], [0, 0, 2], [0, 1, 3]],\n", + " 'comment': 'fvid -> a ccw [lvid,leid,lfid]'}]}" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tet_data" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "autogenerate(\"../src/wmtk/autogen/tet_mesh/autogenerated_tables.{}pp\", tet_data)" ] }, { @@ -237,7 +695,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -251,9 +709,8 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.6" - }, - "orig_nbformat": 4 + "version": "3.10.12" + } }, "nbformat": 4, "nbformat_minor": 2 diff --git a/scripts/array_declaration.template b/scripts/array_declaration.template new file mode 100644 index 0000000000..231ebe99ed --- /dev/null +++ b/scripts/array_declaration.template @@ -0,0 +1,6 @@ +{%- macro print_dimensions(data) %} + {%- if data is sequence -%} + [{{ data|length }}]{{ print_dimensions(data[0]) }} + {%- endif -%} +{% endmacro -%} +const long {{ table.name }}{{ print_dimensions(table.data) }} diff --git a/scripts/autogenerate.py b/scripts/autogenerate.py new file mode 100644 index 0000000000..2b471786fe --- /dev/null +++ b/scripts/autogenerate.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +import jinja2 +import os + + + +# expects a path of the form "path/to/location/name.{}pp" +# data should be a dictionary containing a namespace entry and a list of +# dictionaries called "tables" that contains the "name" and the "data". "data" +# should be list of lists or longs +# example: +# array_data = { +# "namespace": "tri_mesh", +# "tables": [ +# { +# "name": "test", +# "data": [[4,5,6],[2,3,4]] +# }, +# { +# "name": "test2", +# "data": [4,5,6] +# } +# ] +# } + +def autogenerate(path_format, data): + environment = jinja2.Environment(loader=jinja2.FileSystemLoader("./")) + + + # deal with rare cases where the data passed in is a set internally? + def to_list_or_int(dat): + if type(dat) is int: + return dat + else: + return list(map(to_list_or_int,dat)) + + for table_dict in data["tables"]: + table_dict["data"] = to_list_or_int(table_dict["data"]) + # convert table dict data to be lists + + data["local_header_path"] = os.path.basename(path_format.format("h")) + + def write(char,template): + + with open(path_format.format(char),"w") as hpp_file: + hpp_file.write(template.render(data)) + cpp_template = environment.get_template("autogenerated_tables.cpp.template") + write("c",cpp_template) + + hpp_template = environment.get_template("autogenerated_tables.hpp.template") + write("h",hpp_template) + + + + + + +if __name__ == "__main__": + array_data = { + "namespace": "tri_mesh", + "tables": [ + { + "name": "test", + "data": [[4,5,6],[2,3,4]] + }, + { + "name": "test2", + "data": {4,5,6} + } + ] + } + + autogenerate("/tmp/test.{}pp", array_data) diff --git a/scripts/autogenerated_tables.cpp.template b/scripts/autogenerated_tables.cpp.template new file mode 100644 index 0000000000..b192931cbb --- /dev/null +++ b/scripts/autogenerated_tables.cpp.template @@ -0,0 +1,18 @@ +{% macro print_array(data) %} + {%- if data is sequence -%} + { {%- for subdata in data -%} + {{ print_array(subdata) }} + {%- if not loop.last -%},{%- endif -%} + {%- endfor -%} + } + {%- else -%} + {{ data }} + {%- endif -%} +{% endmacro %} +#include "{{ local_header_path }}" +// DO NOT MODIFY, autogenerated from the /scripts directory +namespace wmtk::autogen::{{ namespace }} { + {% for table in tables %} + {% include "array_declaration.template" %} = {{ print_array(table.data) }}; + {% endfor %} +} diff --git a/scripts/autogenerated_tables.hpp.template b/scripts/autogenerated_tables.hpp.template new file mode 100644 index 0000000000..a84e69c44f --- /dev/null +++ b/scripts/autogenerated_tables.hpp.template @@ -0,0 +1,13 @@ +#pragma once + +// DO NOT MODIFY, autogenerated from the /scripts directory + +namespace wmtk::autogen::{{ namespace }} { + {% for table in tables %} + {%- if "comment" in table -%} + // {{ table.comment }} + {%- endif %} + extern {% include "array_declaration.template" -%}; + + {% endfor %} +} diff --git a/scripts/requirements.txt b/scripts/requirements.txt new file mode 100644 index 0000000000..7f7afbf3bf --- /dev/null +++ b/scripts/requirements.txt @@ -0,0 +1 @@ +jinja2 diff --git a/src/wmtk/Primitive.hpp b/src/wmtk/Primitive.hpp index 50b770e707..3eeb9a76af 100644 --- a/src/wmtk/Primitive.hpp +++ b/src/wmtk/Primitive.hpp @@ -18,5 +18,31 @@ constexpr long get_simplex_dimension(PrimitiveType t) return -2; } + +constexpr bool operator==(PrimitiveType a, PrimitiveType b) +{ + return get_simplex_dimension(a) == get_simplex_dimension(b); +} +constexpr bool operator!=(PrimitiveType a, PrimitiveType b) +{ + return get_simplex_dimension(a) != get_simplex_dimension(b); +} +constexpr bool operator<(PrimitiveType a, PrimitiveType b) +{ + return get_simplex_dimension(a) < get_simplex_dimension(b); +} +constexpr bool operator>(PrimitiveType a, PrimitiveType b) +{ + return get_simplex_dimension(a) > get_simplex_dimension(b); +} +constexpr bool operator<=(PrimitiveType a, PrimitiveType b) +{ + return get_simplex_dimension(a) <= get_simplex_dimension(b); +} +constexpr bool operator>=(PrimitiveType a, PrimitiveType b) +{ + return get_simplex_dimension(a) >= get_simplex_dimension(b); +} + std::string_view primitive_type_name(PrimitiveType t); } // namespace wmtk diff --git a/src/wmtk/SimplicialComplex.cpp b/src/wmtk/SimplicialComplex.cpp index f7ab83aec0..234825b185 100644 --- a/src/wmtk/SimplicialComplex.cpp +++ b/src/wmtk/SimplicialComplex.cpp @@ -2,7 +2,7 @@ #include "simplex/SimplexCollection.hpp" #include "simplex/closed_star.hpp" -#include "simplex/coface_cells.hpp" +#include "simplex/top_level_cofaces.hpp" #include "simplex/link.hpp" #include "simplex/open_star.hpp" #include "simplex/simplex_boundary.hpp" @@ -111,7 +111,7 @@ bool SimplicialComplex::simplices_w_boundary_intersect( SimplicialComplex SimplicialComplex::top_coface_simplex(const Mesh& m, const Simplex& s) { - simplex::SimplexCollection coll = simplex::coface_cells(m, s); + simplex::SimplexCollection coll = simplex::top_level_cofaces(m, s); return SimplicialComplex(coll.simplex_vector(), m); } diff --git a/src/wmtk/TetMesh.cpp b/src/wmtk/TetMesh.cpp index a4f972a304..f1f01f5117 100644 --- a/src/wmtk/TetMesh.cpp +++ b/src/wmtk/TetMesh.cpp @@ -1,10 +1,12 @@ #include "TetMesh.hpp" -#include #include #include #include +#include +#include +#include #include namespace wmtk { @@ -107,7 +109,7 @@ Tuple TetMesh::vertex_tuple_from_id(long id) const long t = vt_accessor.index_access().scalar_attribute(id); ConstAccessor tv_accessor = create_accessor(m_tv_handle); auto tv = tv_accessor.index_access().vector_attribute(t); - long lvid = -1, leid = -1, lfid = -1; + long lvid = -1; for (long i = 0; i < 4; ++i) { if (tv(i) == id) { @@ -116,10 +118,8 @@ Tuple TetMesh::vertex_tuple_from_id(long id) const } } - assert(auto_3d_table_complete_vertex[lvid][0] == lvid); - - leid = auto_3d_table_complete_vertex[lvid][1]; - lfid = auto_3d_table_complete_vertex[lvid][2]; + const auto [nlvid, leid, lfid] = autogen::tet_mesh::auto_3d_table_complete_vertex[lvid]; + assert(lvid == nlvid); if (lvid < 0 || leid < 0 || lfid < 0) throw std::runtime_error("vertex_tuple_from_id failed"); @@ -138,7 +138,7 @@ Tuple TetMesh::edge_tuple_from_id(long id) const ConstAccessor te_accessor = create_accessor(m_te_handle); auto te = te_accessor.index_access().vector_attribute(t); - long lvid = -1, leid = -1, lfid = -1; + long leid = -1; for (long i = 0; i < 6; ++i) { if (te(i) == id) { @@ -146,11 +146,9 @@ Tuple TetMesh::edge_tuple_from_id(long id) const break; } } + const auto [lvid, nleid, lfid] = autogen::tet_mesh::auto_3d_table_complete_edge[leid]; + assert(leid == nleid); - assert(auto_3d_table_complete_edge[leid][1] == leid); - - lvid = auto_3d_table_complete_edge[leid][0]; - lfid = auto_3d_table_complete_edge[leid][2]; if (lvid < 0 || leid < 0 || lfid < 0) throw std::runtime_error("edge_tuple_from_id failed"); @@ -169,7 +167,7 @@ Tuple TetMesh::face_tuple_from_id(long id) const ConstAccessor tf_accessor = create_accessor(m_tf_handle); auto tf = tf_accessor.index_access().vector_attribute(t); - long lvid = -1, leid = -1, lfid = -1; + long lfid = -1; for (long i = 0; i < 4; ++i) { if (tf(i) == id) { @@ -178,10 +176,8 @@ Tuple TetMesh::face_tuple_from_id(long id) const } } - assert(auto_3d_table_complete_face[lfid][2] == lfid); - - lvid = auto_3d_table_complete_face[lfid][0]; - leid = auto_3d_table_complete_face[lfid][1]; + const auto [lvid, leid, nlfid] = autogen::tet_mesh::auto_3d_table_complete_face[lfid]; + assert(lfid == nlfid); if (lvid < 0 || leid < 0 || lfid < 0) throw std::runtime_error("face_tuple_from_id failed"); @@ -195,12 +191,9 @@ Tuple TetMesh::face_tuple_from_id(long id) const Tuple TetMesh::tet_tuple_from_id(long id) const { - long lvid = 0, leid = -1, lfid = -1; - - assert(auto_3d_table_complete_vertex[lvid][0] == lvid); - - leid = auto_3d_table_complete_vertex[lvid][1]; - lfid = auto_3d_table_complete_vertex[lvid][2]; + const long lvid = 0; + const auto [nlvid, leid, lfid] = autogen::tet_mesh::auto_3d_table_complete_vertex[lvid]; + assert(lvid == nlvid); ConstAccessor hash_accessor = get_const_cell_hash_accessor(); @@ -283,31 +276,8 @@ long TetMesh::id(const Tuple& tuple, PrimitiveType type) const Tuple TetMesh::switch_tuple(const Tuple& tuple, PrimitiveType type) const { assert(is_valid_slow(tuple)); - const long offset = tuple.m_local_vid * 6 * 4 + tuple.m_local_eid * 4 + tuple.m_local_fid; - // bool ccw = is_ccw(tuple); switch (type) { - case PrimitiveType::Vertex: - return Tuple( - auto_3d_table_vertex[offset][0], - auto_3d_table_vertex[offset][1], - auto_3d_table_vertex[offset][2], - tuple.m_global_cid, - tuple.m_hash); - - case PrimitiveType::Edge: - return Tuple( - auto_3d_table_edge[offset][0], - auto_3d_table_edge[offset][1], - auto_3d_table_edge[offset][2], - tuple.m_global_cid, - tuple.m_hash); - case PrimitiveType::Face: - return Tuple( - auto_3d_table_face[offset][0], - auto_3d_table_face[offset][1], - auto_3d_table_face[offset][2], - tuple.m_global_cid, - tuple.m_hash); + // bool ccw = is_ccw(tuple); case PrimitiveType::Tetrahedron: { // need test const long gvid = id(tuple, PrimitiveType::Vertex); @@ -362,24 +332,22 @@ Tuple TetMesh::switch_tuple(const Tuple& tuple, PrimitiveType type) const assert(is_valid_slow(res)); return res; } - default: throw std::runtime_error("Tuple switch: Invalid primitive type"); break; + default: return autogen::tet_mesh::local_switch_tuple(tuple, type); } } bool TetMesh::is_ccw(const Tuple& tuple) const { assert(is_valid_slow(tuple)); - const long offset = tuple.m_local_vid * 6 * 4 + tuple.m_local_eid * 4 + tuple.m_local_fid; - return autogen::auto_3d_table_ccw[offset][0] == 1; + return autogen::tet_mesh::is_ccw(tuple); } bool TetMesh::is_valid(const Tuple& tuple, ConstAccessor& hash_accessor) const { if (tuple.is_null()) return false; - const long offset = tuple.m_local_vid * 6 * 4 + tuple.m_local_eid * 4 + tuple.m_local_fid; const bool is_connectivity_valid = tuple.m_local_vid >= 0 && tuple.m_local_eid >= 0 && tuple.m_local_fid >= 0 && tuple.m_global_cid >= 0 && - auto_3d_table_ccw[offset][0] >= 0; + autogen::tet_mesh::tuple_is_valid_for_ccw(tuple); if (!is_connectivity_valid) { return false; diff --git a/src/wmtk/TriMesh.cpp b/src/wmtk/TriMesh.cpp index 60f47256b3..a57a8a40bf 100644 --- a/src/wmtk/TriMesh.cpp +++ b/src/wmtk/TriMesh.cpp @@ -2,7 +2,9 @@ #include #include -#include +#include +#include +#include #include namespace wmtk { @@ -90,24 +92,8 @@ Tuple TriMesh::switch_tuple(const Tuple& tuple, PrimitiveType type) const { assert(is_valid_slow(tuple)); bool ccw = is_ccw(tuple); - int offset = tuple.m_local_vid * 3 + tuple.m_local_eid; switch (type) { - case PrimitiveType::Vertex: - return Tuple( - wmtk::autogen::auto_2d_table_vertex[offset][0], - wmtk::autogen::auto_2d_table_vertex[offset][1], - tuple.m_local_fid, - tuple.m_global_cid, - tuple.m_hash); - - case PrimitiveType::Edge: - return Tuple( - wmtk::autogen::auto_2d_table_edge[offset][0], - wmtk::autogen::auto_2d_table_edge[offset][1], - tuple.m_local_fid, - tuple.m_global_cid, - tuple.m_hash); case PrimitiveType::Face: { const long gvid = id(tuple, PrimitiveType::Vertex); const long geid = id(tuple, PrimitiveType::Edge); @@ -146,16 +132,14 @@ Tuple TriMesh::switch_tuple(const Tuple& tuple, PrimitiveType type) const assert(is_valid(res, hash_accessor)); return res; } - case PrimitiveType::Tetrahedron: - default: throw std::runtime_error("Tuple switch: Invalid primitive type"); break; + default: return autogen::tri_mesh::local_switch_tuple(tuple, type); } } bool TriMesh::is_ccw(const Tuple& tuple) const { assert(is_valid_slow(tuple)); - int offset = tuple.m_local_vid * 3 + tuple.m_local_eid; - return autogen::auto_2d_table_ccw[offset][0] == 1; + return autogen::tri_mesh::is_ccw(tuple); } void TriMesh::initialize( @@ -248,8 +232,8 @@ Tuple TriMesh::vertex_tuple_from_id(long id) const auto fv = fv_accessor.index_access().vector_attribute(f); for (long i = 0; i < 3; ++i) { if (fv(i) == id) { - assert(autogen::auto_2d_table_complete_vertex[i][0] == i); - const long leid = autogen::auto_2d_table_complete_vertex[i][1]; + assert(autogen::tri_mesh::auto_2d_table_complete_vertex[i][0] == i); + const long leid = autogen::tri_mesh::auto_2d_table_complete_vertex[i][1]; Tuple v_tuple = Tuple( i, leid, @@ -272,8 +256,8 @@ Tuple TriMesh::edge_tuple_from_id(long id) const auto fe = fe_accessor.index_access().vector_attribute(f); for (long i = 0; i < 3; ++i) { if (fe(i) == id) { - assert(autogen::auto_2d_table_complete_edge[i][1] == i); - const long lvid = autogen::auto_2d_table_complete_edge[i][0]; + assert(autogen::tri_mesh::auto_2d_table_complete_edge[i][1] == i); + const long lvid = autogen::tri_mesh::auto_2d_table_complete_edge[i][0]; ConstAccessor hash_accessor = get_const_cell_hash_accessor(); @@ -289,8 +273,8 @@ Tuple TriMesh::edge_tuple_from_id(long id) const Tuple TriMesh::face_tuple_from_id(long id) const { Tuple f_tuple = Tuple( - autogen::auto_2d_table_complete_vertex[0][0], - autogen::auto_2d_table_complete_vertex[0][1], + autogen::tri_mesh::auto_2d_table_complete_vertex[0][0], + autogen::tri_mesh::auto_2d_table_complete_vertex[0][1], -1, id, get_cell_hash_slow(id) @@ -305,10 +289,10 @@ Tuple TriMesh::face_tuple_from_id(long id) const bool TriMesh::is_valid(const Tuple& tuple, ConstAccessor& hash_accessor) const { if (tuple.is_null()) return false; - int offset = tuple.m_local_vid * 3 + tuple.m_local_eid; + const bool is_connectivity_valid = tuple.m_local_vid >= 0 && tuple.m_local_eid >= 0 && tuple.m_global_cid >= 0 && - autogen::auto_2d_table_ccw[offset][0] >= 0; + autogen::tri_mesh::tuple_is_valid_for_ccw(tuple); if (!is_connectivity_valid) { return false; diff --git a/src/wmtk/Tuple.cpp b/src/wmtk/Tuple.cpp index 640bba3262..7df9066071 100644 --- a/src/wmtk/Tuple.cpp +++ b/src/wmtk/Tuple.cpp @@ -36,15 +36,22 @@ bool Tuple::operator==(const wmtk::Tuple& t) const return std::tie(m_local_vid, m_local_eid, m_local_fid, m_global_cid, m_hash) == std::tie(t.m_local_vid, t.m_local_eid, t.m_local_fid, t.m_global_cid, t.m_hash); } + +bool Tuple::operator<(const wmtk::Tuple& t) const +{ + return std::tie(m_local_vid, m_local_eid, m_local_fid, m_global_cid, m_hash) < + std::tie(t.m_local_vid, t.m_local_eid, t.m_local_fid, t.m_global_cid, t.m_hash); +} bool Tuple::same_ids(const wmtk::Tuple& t) const { - return std::tie(m_local_vid, m_local_eid, m_local_fid, m_global_cid ) == + return std::tie(m_local_vid, m_local_eid, m_local_fid, m_global_cid) == std::tie(t.m_local_vid, t.m_local_eid, t.m_local_fid, t.m_global_cid); } bool Tuple::is_null() const { - return m_local_vid == -1 && m_local_eid == -1 && m_local_fid == -1 && m_global_cid == -1 && m_hash == -1; + return m_local_vid == -1 && m_local_eid == -1 && m_local_fid == -1 && m_global_cid == -1 && + m_hash == -1; } Tuple Tuple::with_updated_hash(long new_hash) const diff --git a/src/wmtk/Tuple.hpp b/src/wmtk/Tuple.hpp index 98d7ac3ebf..c87766ee6e 100644 --- a/src/wmtk/Tuple.hpp +++ b/src/wmtk/Tuple.hpp @@ -10,9 +10,16 @@ class PointMesh; class TriMesh; class EdgeMesh; class TetMesh; +namespace autogen::utils { +class TupleInspector; +} namespace operations { class Operation; } +namespace utils { +// for identifying unique top level simplices between tuples +class TupleCellLessThan; +} // namespace utils class MultiMeshManager; class Tuple @@ -34,6 +41,8 @@ class Tuple friend class TetMesh; friend class operations::Operation; friend class MultiMeshManager; + friend class utils::TupleCellLessThan; + friend class autogen::utils::TupleInspector; // friend long Mesh::id(const Tuple& tuple, const PrimitiveType& type) const; // friend Mesh::is_ccw(const Tuple& tuple) const; // friend Mesh::switch_tuple(const Tuple& tuple, const PrimitiveType& type) const; @@ -54,6 +63,7 @@ class Tuple bool operator==(const Tuple& t) const; bool operator!=(const Tuple& t) const; + bool operator<(const Tuple& t) const; // equality comparison but skips the hash bool same_ids(const Tuple& t) const; diff --git a/src/wmtk/Types.hpp b/src/wmtk/Types.hpp index a1421e87e9..0f9a9926ba 100644 --- a/src/wmtk/Types.hpp +++ b/src/wmtk/Types.hpp @@ -3,15 +3,27 @@ #include namespace wmtk { -using RowVectors2l = Eigen::Matrix; -using RowVectors3l = Eigen::Matrix; -using VectorXl = Eigen::Matrix; -using RowVectors4l = Eigen::Matrix; -using RowVectors6l = Eigen::Matrix; -using RowVectors3d = Eigen::Matrix; +template +using RowVectors = Eigen::Matrix; template using Vector = Eigen::Matrix; template using VectorX = Vector; + +template +using RowVector = Eigen::Matrix; +template +using RowVectorX = RowVector; + +using VectorXl = VectorX; +using RowVector2d = RowVector; +using RowVector3d = RowVector; +using RowVectors2l = RowVectors; +using RowVectors3l = RowVectors; +using RowVectors4l = RowVectors; +using RowVectors6l = RowVectors; +using RowVectors2d = RowVectors; +using RowVectors3d = RowVectors; + } // namespace wmtk diff --git a/src/wmtk/autogen/CMakeLists.txt b/src/wmtk/autogen/CMakeLists.txt index 71cf813cb4..c0364a2250 100644 --- a/src/wmtk/autogen/CMakeLists.txt +++ b/src/wmtk/autogen/CMakeLists.txt @@ -1,6 +1,23 @@ set(SRC_FILES - autogenerated_2d_tables.hpp - autogenerated_3d_tables.hpp + tet_mesh/autogenerated_tables.hpp + tet_mesh/autogenerated_tables.cpp + tet_mesh/local_switch_tuple.hpp + tet_mesh/local_switch_tuple.cpp + tet_mesh/is_ccw.hpp + tet_mesh/is_ccw.cpp + tet_mesh/local_id_table_offset.cpp + tet_mesh/local_id_table_offset.hpp + + tri_mesh/autogenerated_tables.hpp + tri_mesh/autogenerated_tables.cpp + tri_mesh/local_switch_tuple.hpp + tri_mesh/local_switch_tuple.cpp + tri_mesh/is_ccw.hpp + tri_mesh/is_ccw.cpp + tri_mesh/local_id_table_offset.cpp + tri_mesh/local_id_table_offset.hpp + + utils/TupleInspector.hpp ) target_sources(wildmeshing_toolkit PRIVATE ${SRC_FILES}) diff --git a/src/wmtk/autogen/autogenerated_2d_tables.hpp b/src/wmtk/autogen/autogenerated_2d_tables.hpp deleted file mode 100644 index 3d9696a7e8..0000000000 --- a/src/wmtk/autogen/autogenerated_2d_tables.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// Autogenerated by 2d_switch_tables.ipynb - -namespace wmtk { namespace autogen { -static long auto_2d_edges[3][2] = { - {1, 2}, - {0, 2}, - {0, 1} -}; -static long auto_2d_table_vertex[9][2] = { - {-1, -1}, - {2, 1}, - {1, 2}, - {2, 0}, - {-1, -1}, - {0, 2}, - {1, 0}, - {0, 1}, - {-1, -1} -}; -static long auto_2d_table_edge[9][2] = { - {-1, -1}, - {0, 2}, - {0, 1}, - {1, 2}, - {-1, -1}, - {1, 0}, - {2, 1}, - {2, 0}, - {-1, -1} -}; -static long auto_2d_table_ccw[9][1] = { - {-1}, - {0}, - {1}, - {1}, - {-1}, - {0}, - {0}, - {1}, - {-1} -}; -static long auto_2d_table_complete_vertex[3][2] = { - {0, 2}, - {1, 0}, - {2, 1} -}; -static long auto_2d_table_complete_edge[3][2] = { - {1, 0}, - {2, 1}, - {0, 2} -}; -}} diff --git a/src/wmtk/autogen/autogenerated_3d_tables.hpp b/src/wmtk/autogen/autogenerated_3d_tables.hpp deleted file mode 100644 index 0333af69df..0000000000 --- a/src/wmtk/autogen/autogenerated_3d_tables.hpp +++ /dev/null @@ -1,430 +0,0 @@ -// Autogenerated by 3d_switch_tables.ipynb - -namespace wmtk { namespace autogen { -static int auto_3d_edges[6][2] = { - {0, 1}, - {0, 2}, - {0, 3}, - {1, 2}, - {1, 3}, - {2, 3} -}; -static int auto_3d_faces[4][3] = { - {1, 2, 3}, - {0, 2, 3}, - {0, 1, 3}, - {0, 1, 2} -}; -static int auto_3d_table_vertex[96][3] = { - {-1, -1, -1}, - {-1, -1, -1}, - {1, 0, 2}, - {1, 0, 3}, - {-1, -1, -1}, - {2, 1, 1}, - {-1, -1, -1}, - {2, 1, 3}, - {-1, -1, -1}, - {3, 2, 1}, - {3, 2, 2}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {0, 0, 2}, - {0, 0, 3}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {2, 3, 0}, - {-1, -1, -1}, - {-1, -1, -1}, - {2, 3, 3}, - {3, 4, 0}, - {-1, -1, -1}, - {3, 4, 2}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {0, 1, 1}, - {-1, -1, -1}, - {0, 1, 3}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {1, 3, 0}, - {-1, -1, -1}, - {-1, -1, -1}, - {1, 3, 3}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {3, 5, 0}, - {3, 5, 1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {0, 2, 1}, - {0, 2, 2}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {1, 4, 0}, - {-1, -1, -1}, - {1, 4, 2}, - {-1, -1, -1}, - {2, 5, 0}, - {2, 5, 1}, - {-1, -1, -1}, - {-1, -1, -1} -}; -static int auto_3d_table_edge[96][3] = { - {-1, -1, -1}, - {-1, -1, -1}, - {0, 2, 2}, - {0, 1, 3}, - {-1, -1, -1}, - {0, 2, 1}, - {-1, -1, -1}, - {0, 0, 3}, - {-1, -1, -1}, - {0, 1, 1}, - {0, 0, 2}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {1, 4, 2}, - {1, 3, 3}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {1, 4, 0}, - {-1, -1, -1}, - {-1, -1, -1}, - {1, 0, 3}, - {1, 3, 0}, - {-1, -1, -1}, - {1, 0, 2}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {2, 5, 1}, - {-1, -1, -1}, - {2, 3, 3}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {2, 5, 0}, - {-1, -1, -1}, - {-1, -1, -1}, - {2, 1, 3}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {2, 3, 0}, - {2, 1, 1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {3, 5, 1}, - {3, 4, 2}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {3, 5, 0}, - {-1, -1, -1}, - {3, 2, 2}, - {-1, -1, -1}, - {3, 4, 0}, - {3, 2, 1}, - {-1, -1, -1}, - {-1, -1, -1} -}; -static int auto_3d_table_face[96][3] = { - {-1, -1, -1}, - {-1, -1, -1}, - {0, 0, 3}, - {0, 0, 2}, - {-1, -1, -1}, - {0, 1, 3}, - {-1, -1, -1}, - {0, 1, 1}, - {-1, -1, -1}, - {0, 2, 2}, - {0, 2, 1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {1, 0, 3}, - {1, 0, 2}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {1, 3, 3}, - {-1, -1, -1}, - {-1, -1, -1}, - {1, 3, 0}, - {1, 4, 2}, - {-1, -1, -1}, - {1, 4, 0}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {2, 1, 3}, - {-1, -1, -1}, - {2, 1, 1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {2, 3, 3}, - {-1, -1, -1}, - {-1, -1, -1}, - {2, 3, 0}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {2, 5, 1}, - {2, 5, 0}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {3, 2, 2}, - {3, 2, 1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {-1, -1, -1}, - {3, 4, 2}, - {-1, -1, -1}, - {3, 4, 0}, - {-1, -1, -1}, - {3, 5, 1}, - {3, 5, 0}, - {-1, -1, -1}, - {-1, -1, -1} -}; -static int auto_3d_table_ccw[96][1] = { - {-1}, - {-1}, - {1}, - {0}, - {-1}, - {0}, - {-1}, - {1}, - {-1}, - {1}, - {0}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {0}, - {1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {1}, - {-1}, - {-1}, - {0}, - {0}, - {-1}, - {1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {1}, - {-1}, - {0}, - {-1}, - {-1}, - {-1}, - {-1}, - {0}, - {-1}, - {-1}, - {1}, - {-1}, - {-1}, - {-1}, - {-1}, - {1}, - {0}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {0}, - {1}, - {-1}, - {-1}, - {-1}, - {-1}, - {-1}, - {1}, - {-1}, - {0}, - {-1}, - {0}, - {1}, - {-1}, - {-1} -}; -static int auto_3d_table_complete_vertex[4][3] = { - {0, 0, 2}, - {1, 0, 3}, - {2, 1, 1}, - {3, 2, 2} -}; -static int auto_3d_table_complete_edge[6][3] = { - {0, 0, 2}, - {0, 1, 3}, - {0, 2, 1}, - {1, 3, 0}, - {1, 4, 2}, - {2, 5, 0} -}; -static int auto_3d_table_complete_face[4][3] = { - {1, 3, 0}, - {0, 2, 1}, - {0, 0, 2}, - {0, 1, 3} -}; -}} \ No newline at end of file diff --git a/src/wmtk/autogen/tet_mesh/autogenerated_tables.cpp b/src/wmtk/autogen/tet_mesh/autogenerated_tables.cpp new file mode 100644 index 0000000000..72b766b1a4 --- /dev/null +++ b/src/wmtk/autogen/tet_mesh/autogenerated_tables.cpp @@ -0,0 +1,24 @@ + +#include "autogenerated_tables.hpp" +// DO NOT MODIFY, autogenerated from the /scripts directory +namespace wmtk::autogen::tet_mesh { + + const long auto_3d_edges[6][2] = {{0,1},{0,2},{0,3},{1,2},{1,3},{2,3}}; + + const long auto_3d_faces[4][3] = {{1,2,3},{0,2,3},{0,1,3},{0,1,2}}; + + const long auto_3d_table_vertex[96][3] = {{-1,-1,-1},{-1,-1,-1},{1,0,2},{1,0,3},{-1,-1,-1},{2,1,1},{-1,-1,-1},{2,1,3},{-1,-1,-1},{3,2,1},{3,2,2},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{0,0,2},{0,0,3},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{2,3,0},{-1,-1,-1},{-1,-1,-1},{2,3,3},{3,4,0},{-1,-1,-1},{3,4,2},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{0,1,1},{-1,-1,-1},{0,1,3},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{1,3,0},{-1,-1,-1},{-1,-1,-1},{1,3,3},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{3,5,0},{3,5,1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{0,2,1},{0,2,2},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{1,4,0},{-1,-1,-1},{1,4,2},{-1,-1,-1},{2,5,0},{2,5,1},{-1,-1,-1},{-1,-1,-1}}; + + const long auto_3d_table_edge[96][3] = {{-1,-1,-1},{-1,-1,-1},{0,2,2},{0,1,3},{-1,-1,-1},{0,2,1},{-1,-1,-1},{0,0,3},{-1,-1,-1},{0,1,1},{0,0,2},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{1,4,2},{1,3,3},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{1,4,0},{-1,-1,-1},{-1,-1,-1},{1,0,3},{1,3,0},{-1,-1,-1},{1,0,2},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{2,5,1},{-1,-1,-1},{2,3,3},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{2,5,0},{-1,-1,-1},{-1,-1,-1},{2,1,3},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{2,3,0},{2,1,1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{3,5,1},{3,4,2},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{3,5,0},{-1,-1,-1},{3,2,2},{-1,-1,-1},{3,4,0},{3,2,1},{-1,-1,-1},{-1,-1,-1}}; + + const long auto_3d_table_face[96][3] = {{-1,-1,-1},{-1,-1,-1},{0,0,3},{0,0,2},{-1,-1,-1},{0,1,3},{-1,-1,-1},{0,1,1},{-1,-1,-1},{0,2,2},{0,2,1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{1,0,3},{1,0,2},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{1,3,3},{-1,-1,-1},{-1,-1,-1},{1,3,0},{1,4,2},{-1,-1,-1},{1,4,0},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{2,1,3},{-1,-1,-1},{2,1,1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{2,3,3},{-1,-1,-1},{-1,-1,-1},{2,3,0},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{2,5,1},{2,5,0},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{3,2,2},{3,2,1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{-1,-1,-1},{3,4,2},{-1,-1,-1},{3,4,0},{-1,-1,-1},{3,5,1},{3,5,0},{-1,-1,-1},{-1,-1,-1}}; + + const long auto_3d_table_ccw[96] = {-1,-1,1,0,-1,0,-1,1,-1,1,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,-1,-1,-1,-1,-1,-1,-1,-1,1,-1,-1,0,0,-1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,-1,0,-1,-1,-1,-1,0,-1,-1,1,-1,-1,-1,-1,1,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,-1,-1,-1,-1,-1,1,-1,0,-1,0,1,-1,-1}; + + const long auto_3d_table_complete_vertex[4][3] = {{0,0,2},{1,0,3},{2,1,1},{3,2,2}}; + + const long auto_3d_table_complete_edge[6][3] = {{0,0,2},{0,1,3},{0,2,1},{1,3,0},{1,4,2},{2,5,0}}; + + const long auto_3d_table_complete_face[4][3] = {{1,3,0},{0,2,1},{0,0,2},{0,1,3}}; + +} \ No newline at end of file diff --git a/src/wmtk/autogen/tet_mesh/autogenerated_tables.hpp b/src/wmtk/autogen/tet_mesh/autogenerated_tables.hpp new file mode 100644 index 0000000000..d24681ec6b --- /dev/null +++ b/src/wmtk/autogen/tet_mesh/autogenerated_tables.hpp @@ -0,0 +1,34 @@ +#pragma once + +// DO NOT MODIFY, autogenerated from the /scripts directory + +namespace wmtk::autogen::tet_mesh { + // lvids for a specfic leid + extern const long auto_3d_edges[6][2]; + + // lvids for a specific lfid + extern const long auto_3d_faces[4][3]; + + // vertex switch's (tuple_index -> [lvid,leid,lfid]) + extern const long auto_3d_table_vertex[96][3]; + + // edge switch's (tuple_index -> [lvid,leid,lfid]) + extern const long auto_3d_table_edge[96][3]; + + // face switch's (tuple_index -> [lvid,leid,lfid]) + extern const long auto_3d_table_face[96][3]; + + // (tuple_index) -> is_ccw + extern const long auto_3d_table_ccw[96]; + + // lvid -> a ccw [lvid,leid,lfid] + extern const long auto_3d_table_complete_vertex[4][3]; + + // evid -> a ccw [lvid,leid,lfid] + extern const long auto_3d_table_complete_edge[6][3]; + + // fvid -> a ccw [lvid,leid,lfid] + extern const long auto_3d_table_complete_face[4][3]; + + +} \ No newline at end of file diff --git a/src/wmtk/autogen/tet_mesh/is_ccw.cpp b/src/wmtk/autogen/tet_mesh/is_ccw.cpp new file mode 100644 index 0000000000..1f039bf210 --- /dev/null +++ b/src/wmtk/autogen/tet_mesh/is_ccw.cpp @@ -0,0 +1,20 @@ + +#include "is_ccw.hpp" +#include +#include "autogenerated_tables.hpp" +#include "local_id_table_offset.hpp" + +namespace wmtk::autogen::tet_mesh { +bool is_ccw(const Tuple& tuple) +{ + using namespace utils; + const long offset = local_id_table_offset(tuple); + return auto_3d_table_ccw[offset] == 1; +} +bool tuple_is_valid_for_ccw(const Tuple& tuple) +{ + using namespace utils; + const long offset = local_id_table_offset(tuple); + return auto_3d_table_ccw[offset] != -1; +} +} // namespace wmtk::autogen::tet_mesh diff --git a/src/wmtk/autogen/tet_mesh/is_ccw.hpp b/src/wmtk/autogen/tet_mesh/is_ccw.hpp new file mode 100644 index 0000000000..0018b7390b --- /dev/null +++ b/src/wmtk/autogen/tet_mesh/is_ccw.hpp @@ -0,0 +1,9 @@ +#pragma once +#include + +namespace wmtk::autogen::tet_mesh { +bool is_ccw(const Tuple& t); + +// validates whether the tuple local ids are valid for computing ccw'ness +bool tuple_is_valid_for_ccw(const Tuple& t); +} // namespace wmtk::autogen::tet_mesh diff --git a/src/wmtk/autogen/tet_mesh/local_id_table_offset.cpp b/src/wmtk/autogen/tet_mesh/local_id_table_offset.cpp new file mode 100644 index 0000000000..1993eb7243 --- /dev/null +++ b/src/wmtk/autogen/tet_mesh/local_id_table_offset.cpp @@ -0,0 +1,13 @@ +#include "local_id_table_offset.hpp" +#include +#include "autogenerated_tables.hpp" +namespace wmtk::autogen::tet_mesh { +// computes the offset of a tuple's local ids in the tables +long local_id_table_offset(const Tuple& tuple) +{ + using namespace utils; + return TupleInspector::local_vid(tuple) * 6 * 4 + TupleInspector::local_eid(tuple) * 4 + + TupleInspector::local_fid(tuple); +} + +} // namespace wmtk::autogen::tet_mesh diff --git a/src/wmtk/autogen/tet_mesh/local_id_table_offset.hpp b/src/wmtk/autogen/tet_mesh/local_id_table_offset.hpp new file mode 100644 index 0000000000..bd74c73f4a --- /dev/null +++ b/src/wmtk/autogen/tet_mesh/local_id_table_offset.hpp @@ -0,0 +1,9 @@ +#pragma once +#include + + +namespace wmtk::autogen::tet_mesh { +// computes the offset of a tuple's local ids in the tables +long local_id_table_offset(const Tuple& t); + +} // namespace wmtk::autogen::tet_mesh diff --git a/src/wmtk/autogen/tet_mesh/local_switch_tuple.cpp b/src/wmtk/autogen/tet_mesh/local_switch_tuple.cpp new file mode 100644 index 0000000000..0337d2d782 --- /dev/null +++ b/src/wmtk/autogen/tet_mesh/local_switch_tuple.cpp @@ -0,0 +1,46 @@ +#include "local_switch_tuple.hpp" +#include +#include +#include "autogenerated_tables.hpp" +#include "local_id_table_offset.hpp" + + +namespace wmtk::autogen::tet_mesh { +Tuple local_switch_tuple(const Tuple& tuple, PrimitiveType pt) +{ + using namespace utils; + const long offset = local_id_table_offset(tuple); + + + const long global_cid = TupleInspector::global_cid(tuple); + const long hash = TupleInspector::hash(tuple); + switch (pt) { + case PrimitiveType::Vertex: + return Tuple( + auto_3d_table_vertex[offset][0], + auto_3d_table_vertex[offset][1], + auto_3d_table_vertex[offset][2], + global_cid, + hash); + + case PrimitiveType::Edge: + return Tuple( + auto_3d_table_edge[offset][0], + auto_3d_table_edge[offset][1], + auto_3d_table_edge[offset][2], + global_cid, + hash); + case PrimitiveType::Face: + return Tuple( + auto_3d_table_face[offset][0], + auto_3d_table_face[offset][1], + auto_3d_table_face[offset][2], + global_cid, + hash); + + case PrimitiveType::Tetrahedron: + default: throw std::runtime_error("Tuple switch: Invalid primitive type"); break; + } + return Tuple(); +} +} // namespace wmtk::autogen::tet_mesh diff --git a/src/wmtk/autogen/tet_mesh/local_switch_tuple.hpp b/src/wmtk/autogen/tet_mesh/local_switch_tuple.hpp new file mode 100644 index 0000000000..6d9bb0931e --- /dev/null +++ b/src/wmtk/autogen/tet_mesh/local_switch_tuple.hpp @@ -0,0 +1,6 @@ +#pragma once +#include + +namespace wmtk::autogen::tet_mesh { +Tuple local_switch_tuple(const Tuple& t, PrimitiveType pt); +} diff --git a/src/wmtk/autogen/tri_mesh/autogenerated_tables.cpp b/src/wmtk/autogen/tri_mesh/autogenerated_tables.cpp new file mode 100644 index 0000000000..bd1a42cfb9 --- /dev/null +++ b/src/wmtk/autogen/tri_mesh/autogenerated_tables.cpp @@ -0,0 +1,18 @@ + +#include "autogenerated_tables.hpp" +// DO NOT MODIFY, autogenerated from the /scripts directory +namespace wmtk::autogen::tri_mesh { + + const long auto_2d_edges[3][2] = {{1,2},{0,2},{0,1}}; + + const long auto_2d_table_vertex[9][2] = {{-1,-1},{2,1},{1,2},{2,0},{-1,-1},{0,2},{1,0},{0,1},{-1,-1}}; + + const long auto_2d_table_edge[9][2] = {{-1,-1},{0,2},{0,1},{1,2},{-1,-1},{1,0},{2,1},{2,0},{-1,-1}}; + + const long auto_2d_table_ccw[9] = {-1,0,1,1,-1,0,0,1,-1}; + + const long auto_2d_table_complete_vertex[3][2] = {{0,2},{1,0},{2,1}}; + + const long auto_2d_table_complete_edge[3][2] = {{1,0},{2,1},{0,2}}; + +} \ No newline at end of file diff --git a/src/wmtk/autogen/tri_mesh/autogenerated_tables.hpp b/src/wmtk/autogen/tri_mesh/autogenerated_tables.hpp new file mode 100644 index 0000000000..d5dcb1cd98 --- /dev/null +++ b/src/wmtk/autogen/tri_mesh/autogenerated_tables.hpp @@ -0,0 +1,25 @@ +#pragma once + +// DO NOT MODIFY, autogenerated from the /scripts directory + +namespace wmtk::autogen::tri_mesh { + // lvids for a particular leid + extern const long auto_2d_edges[3][2]; + + // vertex switch's (tuple_index -> [lvid,leid]) + extern const long auto_2d_table_vertex[9][2]; + + // edge switch's (tuple_index -> [lvid,leid]) + extern const long auto_2d_table_edge[9][2]; + + // (tuple_index) -> is_ccw + extern const long auto_2d_table_ccw[9]; + + // lvid -> a ccw [lvid,leid] + extern const long auto_2d_table_complete_vertex[3][2]; + + // leid -> a ccw [lvid,leid] + extern const long auto_2d_table_complete_edge[3][2]; + + +} \ No newline at end of file diff --git a/src/wmtk/autogen/tri_mesh/is_ccw.cpp b/src/wmtk/autogen/tri_mesh/is_ccw.cpp new file mode 100644 index 0000000000..5485c189e6 --- /dev/null +++ b/src/wmtk/autogen/tri_mesh/is_ccw.cpp @@ -0,0 +1,20 @@ + +#include "is_ccw.hpp" +#include +#include "autogenerated_tables.hpp" +#include "local_id_table_offset.hpp" + +namespace wmtk::autogen::tri_mesh { +bool is_ccw(const Tuple& tuple) +{ + using namespace utils; + const long offset = local_id_table_offset(tuple); + return auto_2d_table_ccw[offset] == 1; +} +bool tuple_is_valid_for_ccw(const Tuple& tuple) +{ + using namespace utils; + const long offset = local_id_table_offset(tuple); + return auto_2d_table_ccw[offset] != -1; +} +} // namespace wmtk::autogen::tri_mesh diff --git a/src/wmtk/autogen/tri_mesh/is_ccw.hpp b/src/wmtk/autogen/tri_mesh/is_ccw.hpp new file mode 100644 index 0000000000..dd1e912daf --- /dev/null +++ b/src/wmtk/autogen/tri_mesh/is_ccw.hpp @@ -0,0 +1,8 @@ +#pragma once +#include + +namespace wmtk::autogen::tri_mesh { +bool is_ccw(const Tuple& t); +// validates whether the tuple local ids are valid for computing ccw'ness +bool tuple_is_valid_for_ccw(const Tuple& t); +} // namespace wmtk::autogen::tri_mesh diff --git a/src/wmtk/autogen/tri_mesh/local_id_table_offset.cpp b/src/wmtk/autogen/tri_mesh/local_id_table_offset.cpp new file mode 100644 index 0000000000..e99927a060 --- /dev/null +++ b/src/wmtk/autogen/tri_mesh/local_id_table_offset.cpp @@ -0,0 +1,12 @@ +#include "local_id_table_offset.hpp" +#include +#include "autogenerated_tables.hpp" +namespace wmtk::autogen::tri_mesh { +// computes the offset of a tuple's local ids in the tables +long local_id_table_offset(const Tuple& tuple) +{ + using namespace utils; + return TupleInspector::local_vid(tuple) * 3 + TupleInspector::local_eid(tuple); +} + +} // namespace wmtk::autogen::tri_mesh diff --git a/src/wmtk/autogen/tri_mesh/local_id_table_offset.hpp b/src/wmtk/autogen/tri_mesh/local_id_table_offset.hpp new file mode 100644 index 0000000000..407f733661 --- /dev/null +++ b/src/wmtk/autogen/tri_mesh/local_id_table_offset.hpp @@ -0,0 +1,10 @@ +#pragma once +#include + + +namespace wmtk::autogen::tri_mesh { +// computes the offset of a tuple's local ids in the tables +long local_id_table_offset(const Tuple& t); + +} // namespace wmtk::autogen::tri_mesh + diff --git a/src/wmtk/autogen/tri_mesh/local_switch_tuple.cpp b/src/wmtk/autogen/tri_mesh/local_switch_tuple.cpp new file mode 100644 index 0000000000..5203878047 --- /dev/null +++ b/src/wmtk/autogen/tri_mesh/local_switch_tuple.cpp @@ -0,0 +1,36 @@ +#include "local_switch_tuple.hpp" +#include +#include +#include "autogenerated_tables.hpp" +#include "local_id_table_offset.hpp" + + +namespace wmtk::autogen::tri_mesh { +Tuple local_switch_tuple(const Tuple& tuple, PrimitiveType pt) +{ + using namespace utils; + const long offset = local_id_table_offset(tuple); + switch (pt) { + case PrimitiveType::Vertex: + return Tuple( + auto_2d_table_vertex[offset][0], + auto_2d_table_vertex[offset][1], + TupleInspector::local_fid(tuple), + TupleInspector::global_cid(tuple), + TupleInspector::hash(tuple)); + + case PrimitiveType::Edge: + return Tuple( + auto_2d_table_edge[offset][0], + auto_2d_table_edge[offset][1], + TupleInspector::local_fid(tuple), + TupleInspector::global_cid(tuple), + TupleInspector::hash(tuple)); + + case PrimitiveType::Face: + case PrimitiveType::Tetrahedron: + default: throw std::runtime_error("Tuple switch: Invalid primitive type"); break; + } + return Tuple(); +} +} // namespace wmtk::autogen::tri_mesh diff --git a/src/wmtk/autogen/tri_mesh/local_switch_tuple.hpp b/src/wmtk/autogen/tri_mesh/local_switch_tuple.hpp new file mode 100644 index 0000000000..3a67107896 --- /dev/null +++ b/src/wmtk/autogen/tri_mesh/local_switch_tuple.hpp @@ -0,0 +1,6 @@ +#pragma once +#include + +namespace wmtk::autogen::tri_mesh { +Tuple local_switch_tuple(const Tuple& t, PrimitiveType pt); +} diff --git a/src/wmtk/autogen/utils/TupleInspector.hpp b/src/wmtk/autogen/utils/TupleInspector.hpp new file mode 100644 index 0000000000..24fdd5cb7a --- /dev/null +++ b/src/wmtk/autogen/utils/TupleInspector.hpp @@ -0,0 +1,16 @@ +#pragma once +#include + + +namespace wmtk::autogen::utils { +// NOTE: this is just for helping with autogen accessing tuple intenrals. DO NOT USE ELSEWHERE +struct TupleInspector +{ + static long local_vid(const Tuple& t) { return t.m_local_vid; } + static long local_eid(const Tuple& t) { return t.m_local_eid; } + static long local_fid(const Tuple& t) { return t.m_local_fid; } + + static long global_cid(const Tuple& t) { return t.m_global_cid; } + static long hash(const Tuple& t) { return t.m_hash; } +}; +} // namespace wmtk::autogen::utils diff --git a/src/wmtk/simplex/CMakeLists.txt b/src/wmtk/simplex/CMakeLists.txt index 487140f24f..2f2e1b9edb 100644 --- a/src/wmtk/simplex/CMakeLists.txt +++ b/src/wmtk/simplex/CMakeLists.txt @@ -6,10 +6,10 @@ set(SRC_FILES closed_star.cpp closed_star_iterable.hpp closed_star_iterable.cpp - coface_cells.hpp - coface_cells.cpp - coface_cells_iterable.hpp - coface_cells_iterable.cpp + top_level_cofaces.hpp + top_level_cofaces.cpp + top_level_cofaces_iterable.hpp + top_level_cofaces_iterable.cpp link.hpp link.cpp link_iterable.hpp @@ -28,8 +28,8 @@ set(SRC_FILES iterable/LinkIterable.cpp iterable/OpenStarIterable.hpp iterable/OpenStarIterable.cpp - iterable/CofaceCellsIterable.hpp - iterable/CofaceCellsIterable.cpp + iterable/TopLevelCofacesIterable.hpp + iterable/TopLevelCofacesIterable.cpp iterable/SimplexBoundaryIterable.hpp iterable/SimplexBoundaryIterable.cpp internal/SimplexEqualFunctor.hpp diff --git a/src/wmtk/simplex/SimplexCollection.hpp b/src/wmtk/simplex/SimplexCollection.hpp index 8fa941c39f..f98073a2eb 100644 --- a/src/wmtk/simplex/SimplexCollection.hpp +++ b/src/wmtk/simplex/SimplexCollection.hpp @@ -10,10 +10,11 @@ namespace wmtk::simplex { class SimplexCollection { public: - SimplexCollection(const Mesh& mesh) + SimplexCollection(const Mesh& mesh, std::vector&& simplices = {}) : m_mesh{mesh} , m_simplex_is_less(mesh) , m_simplex_is_equal(mesh) + , m_simplices(std::move(simplices)) {} /** @@ -72,4 +73,4 @@ class SimplexCollection const Mesh& m_mesh; std::vector m_simplices; }; -} // namespace wmtk::simplex \ No newline at end of file +} // namespace wmtk::simplex diff --git a/src/wmtk/simplex/closed_star.cpp b/src/wmtk/simplex/closed_star.cpp index 868bc5c577..9f7927d780 100644 --- a/src/wmtk/simplex/closed_star.cpp +++ b/src/wmtk/simplex/closed_star.cpp @@ -3,7 +3,7 @@ #include #include -#include "coface_cells.hpp" +#include "top_level_cofaces.hpp" #include "simplex_boundary.hpp" namespace wmtk::simplex { @@ -14,12 +14,12 @@ SimplexCollection closed_star(const Mesh& mesh, const Simplex& simplex, const bo collection.add(simplex); - const SimplexCollection coface_cells_collection = + const SimplexCollection top_level_cofaces_collection = mesh.top_simplex_type() == PrimitiveType::Face - ? coface_cells(static_cast(mesh), simplex, false) - : coface_cells(static_cast(mesh), simplex, false); + ? top_level_cofaces(static_cast(mesh), simplex, false) + : top_level_cofaces(static_cast(mesh), simplex, false); - for (const Simplex& coface_cell : coface_cells_collection.simplex_vector()) { + for (const Simplex& coface_cell : top_level_cofaces_collection.simplex_vector()) { collection.add(coface_cell); const SimplexCollection cell_boundary = simplex_boundary(mesh, coface_cell); collection.add(cell_boundary); diff --git a/src/wmtk/simplex/coface_cells.cpp b/src/wmtk/simplex/coface_cells.cpp deleted file mode 100644 index e72dcd01b3..0000000000 --- a/src/wmtk/simplex/coface_cells.cpp +++ /dev/null @@ -1,176 +0,0 @@ -#include "coface_cells.hpp" - -#include -#include - -#include -#include - -#include "internal/SimplexLessFunctor.hpp" - -namespace wmtk::simplex { - -SimplexCollection -coface_cells(const TriMesh& mesh, const Simplex& simplex, const bool sort_and_clean) -{ - SimplexCollection collection(mesh); - - internal::SimplexLessFunctor sef(mesh); - - switch (simplex.primitive_type()) { - case PrimitiveType::Vertex: { - std::set touched_cells(sef); - std::queue q; - q.push(simplex.tuple()); - while (!q.empty()) { - const Tuple t = q.front(); - q.pop(); - - { - // check if cell already exists - const auto [it, success] = touched_cells.insert(Simplex::face(t)); - if (!success) { - continue; - } - } - - collection.add(Simplex::face(t)); - - if (!mesh.is_boundary(t)) { - q.push(mesh.switch_face(t)); - } - const Tuple t_other = mesh.switch_edge(t); - if (!mesh.is_boundary(t_other)) { - q.push(mesh.switch_face(t_other)); - } - } - break; - } - case PrimitiveType::Edge: { - const Tuple& t = simplex.tuple(); - collection.add(Simplex::face(t)); - if (!mesh.is_boundary(t)) { - collection.add(Simplex::face(mesh.switch_face(t))); - } - break; - } - case PrimitiveType::Face: { - collection.add(simplex); - break; - } - default: assert(false); break; - } - - if (sort_and_clean) { - collection.sort_and_clean(); - } - - return collection; -} - -SimplexCollection -coface_cells(const TetMesh& mesh, const Simplex& simplex, const bool sort_and_clean) -{ - SimplexCollection collection(mesh); - - internal::SimplexLessFunctor sef(mesh); - - switch (simplex.primitive_type()) { - case PrimitiveType::Vertex: { - std::set touched_cells(sef); - std::queue q; - q.push(simplex.tuple()); - while (!q.empty()) { - const Tuple t = q.front(); - q.pop(); - - { - // check if cell already exists - const auto [it, success] = touched_cells.insert(Simplex::tetrahedron(t)); - if (!success) { - continue; - } - } - - collection.add(Simplex::tetrahedron(t)); - - const Tuple& t1 = t; - const Tuple t2 = mesh.switch_face(t); - const Tuple t3 = mesh.switch_face(mesh.switch_edge(t)); - - if (!mesh.is_boundary(t1)) { - q.push(mesh.switch_tetrahedron(t1)); - } - if (!mesh.is_boundary(t2)) { - q.push(mesh.switch_tetrahedron(t2)); - } - if (!mesh.is_boundary(t3)) { - q.push(mesh.switch_tetrahedron(t3)); - } - } - break; - } - case PrimitiveType::Edge: { - std::set touched_cells(sef); - std::queue q; - q.push(simplex.tuple()); - while (!q.empty()) { - const Tuple t = q.front(); - q.pop(); - - { - // check if cell already exists - const auto [it, success] = touched_cells.insert(Simplex::tetrahedron(t)); - if (!success) { - continue; - } - } - - collection.add(Simplex::tetrahedron(t)); - - const Tuple& t1 = t; - const Tuple t2 = mesh.switch_face(t); - - if (!mesh.is_boundary(t1)) { - q.push(mesh.switch_tetrahedron(t1)); - } - if (!mesh.is_boundary(t2)) { - q.push(mesh.switch_tetrahedron(t2)); - } - } - break; - } - case PrimitiveType::Face: { - const Tuple& t = simplex.tuple(); - collection.add(Simplex::tetrahedron(t)); - if (!mesh.is_boundary(t)) { - collection.add(Simplex::tetrahedron(mesh.switch_tetrahedron(t))); - } - break; - } - case PrimitiveType::Tetrahedron: { - collection.add(simplex); - break; - } - default: assert(false); break; - } - - if (sort_and_clean) { - collection.sort_and_clean(); - } - - return collection; -} - -SimplexCollection coface_cells(const Mesh& mesh, const Simplex& simplex, const bool sort_and_clean) -{ - switch (mesh.top_simplex_type()) { - case PrimitiveType::Face: - return coface_cells(static_cast(mesh), simplex, sort_and_clean); - case PrimitiveType::Tetrahedron: - return coface_cells(static_cast(mesh), simplex, sort_and_clean); - default: assert(false); throw "unknown mesh type in coface_cells"; - } -} - -} // namespace wmtk::simplex \ No newline at end of file diff --git a/src/wmtk/simplex/coface_cells.hpp b/src/wmtk/simplex/coface_cells.hpp deleted file mode 100644 index 1c4f884525..0000000000 --- a/src/wmtk/simplex/coface_cells.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "SimplexCollection.hpp" - -namespace wmtk::simplex { - -SimplexCollection -coface_cells(const TriMesh& mesh, const Simplex& simplex, const bool sort_and_clean = true); - -SimplexCollection -coface_cells(const TetMesh& mesh, const Simplex& simplex, const bool sort_and_clean = true); - -SimplexCollection -coface_cells(const Mesh& mesh, const Simplex& simplex, const bool sort_and_clean = true); - -} // namespace wmtk::simplex \ No newline at end of file diff --git a/src/wmtk/simplex/coface_cells_iterable.cpp b/src/wmtk/simplex/coface_cells_iterable.cpp deleted file mode 100644 index 4ac3ae204b..0000000000 --- a/src/wmtk/simplex/coface_cells_iterable.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "coface_cells_iterable.hpp" - -namespace wmtk::simplex { - -CofaceCellsIterable coface_cells_iterable(const Mesh& mesh, const Simplex& simplex) -{ - return CofaceCellsIterable(mesh, simplex); -} - -} // namespace wmtk::simplex \ No newline at end of file diff --git a/src/wmtk/simplex/coface_cells_iterable.hpp b/src/wmtk/simplex/coface_cells_iterable.hpp deleted file mode 100644 index 02795f1931..0000000000 --- a/src/wmtk/simplex/coface_cells_iterable.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "iterable/CofaceCellsIterable.hpp" - -namespace wmtk::simplex { -CofaceCellsIterable coface_cells_iterable(const Mesh& mesh, const Simplex& simplex); -} \ No newline at end of file diff --git a/src/wmtk/simplex/iterable/CofaceCellsIterable.cpp b/src/wmtk/simplex/iterable/CofaceCellsIterable.cpp deleted file mode 100644 index 5833b89406..0000000000 --- a/src/wmtk/simplex/iterable/CofaceCellsIterable.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "CofaceCellsIterable.hpp" - -#include - -namespace wmtk::simplex { - - -CofaceCellsIterable::CofaceCellsIterable(const Mesh& mesh, const Simplex& simplex) - : m_collection(coface_cells(mesh, simplex)) -{} - -} // namespace wmtk::simplex \ No newline at end of file diff --git a/src/wmtk/simplex/iterable/TopLevelCofacesIterable.cpp b/src/wmtk/simplex/iterable/TopLevelCofacesIterable.cpp new file mode 100644 index 0000000000..8444c4e01c --- /dev/null +++ b/src/wmtk/simplex/iterable/TopLevelCofacesIterable.cpp @@ -0,0 +1,12 @@ +#include "TopLevelCofacesIterable.hpp" + +#include + +namespace wmtk::simplex { + + +TopLevelCofacesIterable::TopLevelCofacesIterable(const Mesh& mesh, const Simplex& simplex) + : m_collection(top_level_cofaces(mesh, simplex)) +{} + +} // namespace wmtk::simplex \ No newline at end of file diff --git a/src/wmtk/simplex/iterable/CofaceCellsIterable.hpp b/src/wmtk/simplex/iterable/TopLevelCofacesIterable.hpp similarity index 78% rename from src/wmtk/simplex/iterable/CofaceCellsIterable.hpp rename to src/wmtk/simplex/iterable/TopLevelCofacesIterable.hpp index 3dc9d2e53a..a2c07e755b 100644 --- a/src/wmtk/simplex/iterable/CofaceCellsIterable.hpp +++ b/src/wmtk/simplex/iterable/TopLevelCofacesIterable.hpp @@ -7,10 +7,10 @@ namespace wmtk::simplex { -class CofaceCellsIterable +class TopLevelCofacesIterable { public: - CofaceCellsIterable(const Mesh& mesh, const Simplex& simplex); + TopLevelCofacesIterable(const Mesh& mesh, const Simplex& simplex); auto begin() { return m_collection.simplex_vector().begin(); } auto end() { return m_collection.simplex_vector().end(); } diff --git a/src/wmtk/simplex/open_star.cpp b/src/wmtk/simplex/open_star.cpp index 0d7ffb9349..5c2d58d3eb 100644 --- a/src/wmtk/simplex/open_star.cpp +++ b/src/wmtk/simplex/open_star.cpp @@ -3,7 +3,7 @@ #include #include -#include "coface_cells.hpp" +#include "top_level_cofaces.hpp" #include "simplex_boundary.hpp" namespace wmtk::simplex { @@ -14,12 +14,12 @@ SimplexCollection open_star(const Mesh& mesh, const Simplex& simplex, const bool collection.add(simplex); - const SimplexCollection coface_cells_collection = + const SimplexCollection top_level_cofaces_collection = mesh.top_simplex_type() == PrimitiveType::Face - ? coface_cells(static_cast(mesh), simplex, false) - : coface_cells(static_cast(mesh), simplex, false); + ? top_level_cofaces(static_cast(mesh), simplex, false) + : top_level_cofaces(static_cast(mesh), simplex, false); - for (const Simplex& coface_cell : coface_cells_collection.simplex_vector()) { + for (const Simplex& coface_cell : top_level_cofaces_collection.simplex_vector()) { collection.add(coface_cell); const SimplexCollection cell_boundary = simplex_boundary(mesh, coface_cell); diff --git a/src/wmtk/simplex/top_level_cofaces.cpp b/src/wmtk/simplex/top_level_cofaces.cpp new file mode 100644 index 0000000000..72d0cde670 --- /dev/null +++ b/src/wmtk/simplex/top_level_cofaces.cpp @@ -0,0 +1,260 @@ +#include "top_level_cofaces.hpp" +#include + +#include +#include + +#include +#include + +#include "internal/SimplexLessFunctor.hpp" + +namespace wmtk::simplex { + +namespace { + + +std::vector tuple_to_simplices(const std::vector& tups, PrimitiveType primitive) +{ + std::vector r; + r.reserve(tups.size()); + std::transform(tups.begin(), tups.end(), std::back_inserter(r), [primitive](const Tuple& t) { + return Simplex(primitive, t); + }); + return r; +} + +std::vector top_level_cofaces_tuples_vertex(const TriMesh& mesh, const Tuple& t) +{ + std::vector collection; + + std::set touched_cells; + std::queue q; + q.push(t); + while (!q.empty()) { + const Tuple t = q.front(); + q.pop(); + + { + // check if cell already exists + const auto [it, did_insert] = touched_cells.insert(t); + if (!did_insert) { + continue; + } + } + collection.emplace_back(t); + + if (!mesh.is_boundary(t)) { + q.push(mesh.switch_face(t)); + } + const Tuple t_other = mesh.switch_edge(t); + if (!mesh.is_boundary(t_other)) { + q.push(mesh.switch_face(t_other)); + } + } + return collection; +} +std::vector top_level_cofaces_tuples_edge(const TriMesh& mesh, const Tuple& t) +{ + std::vector collection; + collection.emplace_back(t); + if (!mesh.is_boundary(t)) { + collection.emplace_back(mesh.switch_face(t)); + } + + return collection; +} +std::vector top_level_cofaces_tuples_face(const TriMesh& mesh, const Tuple& t) +{ + return {t}; +} + +std::vector top_level_cofaces_tuples_vertex(const TetMesh& mesh, const Tuple& t) +{ + std::vector collection; + std::set touched_cells; + std::queue q; + q.push(t); + while (!q.empty()) { + const Tuple t = q.front(); + q.pop(); + + { + // check if cell already exists + const auto [it, was_inserted] = touched_cells.insert(t); + if (!was_inserted) { + continue; + } + } + + collection.emplace_back(t); + + const Tuple& t1 = t; + const Tuple t2 = mesh.switch_face(t); + const Tuple t3 = mesh.switch_tuples(t, {PrimitiveType::Edge, PrimitiveType::Face}); + + if (!mesh.is_boundary(t1)) { + q.push(mesh.switch_tetrahedron(t1)); + } + if (!mesh.is_boundary(t2)) { + q.push(mesh.switch_tetrahedron(t2)); + } + if (!mesh.is_boundary(t3)) { + q.push(mesh.switch_tetrahedron(t3)); + } + } + return collection; +} +std::vector top_level_cofaces_tuples_edge(const TetMesh& mesh, const Tuple& t) +{ + std::vector collection; + std::set touched_cells; + std::queue q; + q.push(t); + while (!q.empty()) { + const Tuple t = q.front(); + q.pop(); + + { + // check if cell already exists + const auto [it, was_inserted] = touched_cells.insert(t); + if (!was_inserted) { + continue; + } + } + + collection.emplace_back(t); + + const Tuple& t1 = t; + const Tuple t2 = mesh.switch_face(t); + + if (!mesh.is_boundary(t1)) { + q.push(mesh.switch_tetrahedron(t1)); + } + if (!mesh.is_boundary(t2)) { + q.push(mesh.switch_tetrahedron(t2)); + } + } + return collection; +} + +std::vector top_level_cofaces_tuples_face(const TetMesh& mesh, const Tuple& t) +{ + std::vector collection = {t}; + if (!mesh.is_boundary(t)) { + collection.emplace_back(mesh.switch_tetrahedron(t)); + } + return collection; +} +std::vector top_level_cofaces_tuples_tet(const TetMesh& mesh, const Tuple& t) +{ + return {t}; +} + + +} // namespace + +std::vector top_level_cofaces_tuples(const TriMesh& mesh, const Simplex& simplex) +{ + std::vector collection; + + + switch (simplex.primitive_type()) { + case PrimitiveType::Vertex: { + collection = top_level_cofaces_tuples_vertex(mesh, simplex.tuple()); + break; + } + case PrimitiveType::Edge: { + collection = top_level_cofaces_tuples_edge(mesh, simplex.tuple()); + break; + } + case PrimitiveType::Face: { + collection = top_level_cofaces_tuples_face(mesh, simplex.tuple()); + break; + } + default: assert(false); break; + } + + + return collection; +} + +std::vector top_level_cofaces_tuples(const TetMesh& mesh, const Simplex& simplex) +{ + std::vector collection; + + + switch (simplex.primitive_type()) { + case PrimitiveType::Vertex: { + collection = top_level_cofaces_tuples_vertex(mesh, simplex.tuple()); + break; + } + case PrimitiveType::Edge: { + collection = top_level_cofaces_tuples_edge(mesh, simplex.tuple()); + break; + } + case PrimitiveType::Face: { + collection = top_level_cofaces_tuples_face(mesh, simplex.tuple()); + break; + } + case PrimitiveType::Tetrahedron: { + collection = top_level_cofaces_tuples_tet(mesh, simplex.tuple()); + break; + } + default: assert(false); break; + } + + return collection; +} + +std::vector top_level_cofaces_tuples(const Mesh& mesh, const Simplex& simplex) +{ + switch (mesh.top_simplex_type()) { + case PrimitiveType::Face: + return top_level_cofaces_tuples(static_cast(mesh), simplex); + case PrimitiveType::Tetrahedron: + return top_level_cofaces_tuples(static_cast(mesh), simplex); + default: assert(false); throw "unknown mesh type in top_level_cofaces_tuples"; + } +} + +SimplexCollection +top_level_cofaces(const TriMesh& mesh, const Simplex& simplex, const bool sort_and_clean) +{ + SimplexCollection collection( + mesh, + tuple_to_simplices(top_level_cofaces_tuples(mesh, simplex), PrimitiveType::Face)); + if (sort_and_clean) { + collection.sort_and_clean(); + } + + return collection; +} + +SimplexCollection +top_level_cofaces(const TetMesh& mesh, const Simplex& simplex, const bool sort_and_clean) +{ + SimplexCollection collection( + mesh, + tuple_to_simplices(top_level_cofaces_tuples(mesh, simplex), PrimitiveType::Tetrahedron)); + if (sort_and_clean) { + collection.sort_and_clean(); + } + + return collection; +} + +SimplexCollection +top_level_cofaces(const Mesh& mesh, const Simplex& simplex, const bool sort_and_clean) +{ + SimplexCollection collection( + mesh, + tuple_to_simplices(top_level_cofaces_tuples(mesh, simplex), mesh.top_simplex_type())); + if (sort_and_clean) { + collection.sort_and_clean(); + } + + return collection; +} + +} // namespace wmtk::simplex diff --git a/src/wmtk/simplex/top_level_cofaces.hpp b/src/wmtk/simplex/top_level_cofaces.hpp new file mode 100644 index 0000000000..46db99c23d --- /dev/null +++ b/src/wmtk/simplex/top_level_cofaces.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include "SimplexCollection.hpp" + +namespace wmtk::simplex { + + +// Returns one simplex for every top level coface of the input simplex. +// The tuple held by each Simplex is guaranteed to contain the child simplex (and all oother lower +// order simplices of the tuple) In particular, for any simplex (t, k) for tuple t, dimension k, +// this function returns simplices (u,m) such that \forall i \leq k, id(t,i) = id(u,i) +SimplexCollection +top_level_cofaces(const TriMesh& mesh, const Simplex& simplex, const bool sort_and_clean = true); + +SimplexCollection +top_level_cofaces(const TetMesh& mesh, const Simplex& simplex, const bool sort_and_clean = true); + +SimplexCollection +top_level_cofaces(const Mesh& mesh, const Simplex& simplex, const bool sort_and_clean = true); + + +// variants of top_level_cofaces that just use a std::vector because every return value has +// the same simplex dimension +std::vector top_level_cofaces_tuples(const TriMesh& mesh, const Simplex& simplex); + +std::vector top_level_cofaces_tuples(const TetMesh& mesh, const Simplex& simplex); + +std::vector top_level_cofaces_tuples(const Mesh& mesh, const Simplex& simplex); + +} // namespace wmtk::simplex diff --git a/src/wmtk/simplex/top_level_cofaces_iterable.cpp b/src/wmtk/simplex/top_level_cofaces_iterable.cpp new file mode 100644 index 0000000000..4fdd43153a --- /dev/null +++ b/src/wmtk/simplex/top_level_cofaces_iterable.cpp @@ -0,0 +1,10 @@ +#include "top_level_cofaces_iterable.hpp" + +namespace wmtk::simplex { + +TopLevelCofacesIterable top_level_cofaces_iterable(const Mesh& mesh, const Simplex& simplex) +{ + return TopLevelCofacesIterable(mesh, simplex); +} + +} // namespace wmtk::simplex \ No newline at end of file diff --git a/src/wmtk/simplex/top_level_cofaces_iterable.hpp b/src/wmtk/simplex/top_level_cofaces_iterable.hpp new file mode 100644 index 0000000000..1ccd25bf3a --- /dev/null +++ b/src/wmtk/simplex/top_level_cofaces_iterable.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include "iterable/TopLevelCofacesIterable.hpp" + +namespace wmtk::simplex { +TopLevelCofacesIterable top_level_cofaces_iterable(const Mesh& mesh, const Simplex& simplex); +} \ No newline at end of file diff --git a/src/wmtk/utils/TupleCellLessThanFunctor.hpp b/src/wmtk/utils/TupleCellLessThanFunctor.hpp new file mode 100644 index 0000000000..97654be8c2 --- /dev/null +++ b/src/wmtk/utils/TupleCellLessThanFunctor.hpp @@ -0,0 +1,10 @@ +#pragma once +#include + +namespace wmtk::utils { + struct TupleCellLessThan { + bool operator()(const Tuple& a, const Tuple& b) const { + return a.m_global_cid < b.m_global_cid; + } + }; +} diff --git a/src/wmtk/utils/tetmesh_topology_initialization.cpp b/src/wmtk/utils/tetmesh_topology_initialization.cpp index 270a067439..428eb01443 100644 --- a/src/wmtk/utils/tetmesh_topology_initialization.cpp +++ b/src/wmtk/utils/tetmesh_topology_initialization.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include namespace wmtk { @@ -36,9 +36,9 @@ tetmesh_topology_initialization(Eigen::Ref T) for (int t = 0; t < T.rows(); ++t) { for (int i = 0; i < 4; ++i) { // v1 v2 v3 f ei - long x = T(t, static_cast(autogen::auto_3d_faces[i][0])); - long y = T(t, static_cast(autogen::auto_3d_faces[i][1])); - long z = T(t, static_cast(autogen::auto_3d_faces[i][2])); + long x = T(t, static_cast(autogen::tet_mesh::auto_3d_faces[i][0])); + long y = T(t, static_cast(autogen::tet_mesh::auto_3d_faces[i][1])); + long z = T(t, static_cast(autogen::tet_mesh::auto_3d_faces[i][2])); if (x > y) std::swap(x, y); if (y > z) std::swap(y, z); if (x > y) std::swap(x, y); @@ -115,8 +115,8 @@ tetmesh_topology_initialization(Eigen::Ref T) for (int t = 0; t < T.rows(); ++t) { for (int i = 0; i < 6; ++i) { // v1 v2 f ei - long x = T(t, static_cast(autogen::auto_3d_edges[i][0])); - long y = T(t, static_cast(autogen::auto_3d_edges[i][1])); + long x = T(t, static_cast(autogen::tet_mesh::auto_3d_edges[i][0])); + long y = T(t, static_cast(autogen::tet_mesh::auto_3d_edges[i][1])); if (x > y) std::swap(x, y); std::vector r(5); @@ -183,4 +183,4 @@ tetmesh_topology_initialization(Eigen::Ref T) return {TE, TF, TT, VT, ET, FT}; } -} // namespace wmtk \ No newline at end of file +} // namespace wmtk diff --git a/src/wmtk/utils/trimesh_topology_initialization.cpp b/src/wmtk/utils/trimesh_topology_initialization.cpp index 8745c795b1..1abf8bff76 100644 --- a/src/wmtk/utils/trimesh_topology_initialization.cpp +++ b/src/wmtk/utils/trimesh_topology_initialization.cpp @@ -1,19 +1,18 @@ #include "trimesh_topology_initialization.h" -#include -#include #include +#include +#include #include namespace wmtk { - -std::tuple trimesh_topology_initialization( +std::tuple trimesh_topology_initialization( Eigen::Ref F) { RowVectors3l FE, FF; VectorXl VF, EF; - + // Make sure there are 3 columns assert(F.cols() == 3); @@ -33,8 +32,9 @@ std::tuple trimesh_topology_initial for (int t = 0; t < F.rows(); ++t) { for (int i = 0; i < 3; ++i) { // v1 v2 v3 f ei - long x = F(t,static_cast(wmtk::autogen::auto_2d_edges[i][0])); - long y = F(t,static_cast(wmtk::autogen::auto_2d_edges[i][1])); + const auto& [f0, f1] = wmtk::autogen::tri_mesh::auto_2d_edges[i]; + long x = F(t, f0); + long y = F(t, f1); if (x > y) std::swap(x, y); std::vector r(4); @@ -51,7 +51,7 @@ std::tuple trimesh_topology_initial VF = VectorXl::Constant(vertex_count, 1, -1); for (int i = 0; i < F.rows(); ++i) { for (int j = 0; j < 3; ++j) { - VF[F(i,j)] = i; + VF[F(i, j)] = i; } } diff --git a/tests/components/CMakeLists.txt b/tests/components/CMakeLists.txt index 49a4f4cdb0..2eaf989711 100644 --- a/tests/components/CMakeLists.txt +++ b/tests/components/CMakeLists.txt @@ -1,5 +1,6 @@ # Sources set(TEST_SOURCES + test_component_delaunay.cpp test_component_input.cpp test_component_mesh_info.cpp test_component_output.cpp diff --git a/tests/components/test_component_delaunay.cpp b/tests/components/test_component_delaunay.cpp new file mode 100644 index 0000000000..5a09e60756 --- /dev/null +++ b/tests/components/test_component_delaunay.cpp @@ -0,0 +1,138 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using json = nlohmann::json; + +const std::filesystem::path data_dir = WMTK_DATA_DIR; + +TEST_CASE("component_delaunay", "[components][delaunay][.]") +{ + std::map files; + + // input + { + json input_component_json = { + {"type", "input"}, + {"name", "input_mesh"}, + {"cell_dimension", 0}, + {"file", data_dir / "bunny.off"}}; + wmtk::components::input(input_component_json, files); + } + + json component_json = { + {"type", "input"}, + {"input", "input_mesh"}, + {"output", "output_mesh"}, + {"cell_dimension", 3}}; + + CHECK_NOTHROW(wmtk::components::delaunay(component_json, files)); + + { + json component_json = { + {"type", "output"}, + {"input", "output_mesh"}, + {"cell_dimension", 3}, + {"file", "component_delaunay_3d"}}; + + CHECK_NOTHROW(wmtk::components::output(component_json, files)); + } +} + +TEST_CASE("delaunay_2d_five_points", "[components][delaunay]") +{ + // create points + wmtk::RowVectors2d points(5, 2); + points.row(0) << -1, -1; + points.row(1) << -1, 1; + points.row(2) << 1, -1; + points.row(3) << 1, 1; + points.row(4) << 0, 0; + + Eigen::MatrixXd vertices; + Eigen::MatrixXi faces; + CHECK_NOTHROW(std::tie(vertices, faces) = wmtk::components::internal::delaunay_2d(points)); + + if (false) { + paraviewo::VTUWriter writer; + writer.write_mesh("delaunay_2d_five_points.vtu", vertices, faces); + } +} + +TEST_CASE("delaunay_2d_random", "[components][delaunay]") +{ + std::uniform_real_distribution distribution(-1, 1); + std::default_random_engine random_engine; + + // create points + wmtk::RowVectors2d points(100, 2); + for (size_t i = 0; i < 100; ++i) { + const double x = distribution(random_engine); + const double y = distribution(random_engine); + points.row(i) << x, y; + } + + Eigen::MatrixXd vertices; + Eigen::MatrixXi faces; + CHECK_NOTHROW(std::tie(vertices, faces) = wmtk::components::internal::delaunay_2d(points)); + + if (false) { + paraviewo::VTUWriter writer; + writer.write_mesh("delaunay_2d_random.vtu", vertices, faces); + } +} + +TEST_CASE("delaunay_3d_nine_points", "[components][delaunay][.]") +{ + // create points + wmtk::RowVectors3d points(9, 3); + points.row(0) << -1, -1, -1; + points.row(1) << 1, -1, -1; + points.row(2) << -1, 1, -1; + points.row(3) << -1, -1, 1; + points.row(4) << 1, 1, -1; + points.row(5) << -1, 1, 1; + points.row(6) << 1, -1, 1; + points.row(7) << 1, 1, 1; + points.row(8) << 0, 0, 0; + + Eigen::MatrixXd vertices; + Eigen::MatrixXi faces; + CHECK_NOTHROW(std::tie(vertices, faces) = wmtk::components::internal::delaunay_3d(points)); + + if (false) { + paraviewo::VTUWriter writer; + writer.write_mesh("delaunay_3d_nine_points.vtu", vertices, faces); + } +} + +TEST_CASE("delaunay_3d_random", "[components][delaunay][.]") +{ + std::uniform_real_distribution distribution(-1, 1); + std::default_random_engine random_engine; + + // create points + wmtk::RowVectors3d points(100, 3); + for (size_t i = 0; i < 100; ++i) { + const double x = distribution(random_engine); + const double y = distribution(random_engine); + const double z = distribution(random_engine); + points.row(i) << x, y, z; + } + + Eigen::MatrixXd vertices; + Eigen::MatrixXi faces; + CHECK_NOTHROW(std::tie(vertices, faces) = wmtk::components::internal::delaunay_3d(points)); + + if (false) { + paraviewo::VTUWriter writer; + writer.write_mesh("delaunay_3d_random.vtu", vertices, faces); + } +} diff --git a/tests/components/test_component_input.cpp b/tests/components/test_component_input.cpp index 9396041614..7dbf8f1664 100644 --- a/tests/components/test_component_input.cpp +++ b/tests/components/test_component_input.cpp @@ -13,6 +13,7 @@ TEST_CASE("component_input", "[components][input][.]") json component_json = { {"type", "input"}, {"name", "input_mesh"}, + {"cell_dimension", 2}, {"file", data_dir / "bunny.off"}}; std::map files; @@ -25,9 +26,23 @@ TEST_CASE("component_input", "[components][input][.]") json component_json = { {"type", "input"}, {"name", "input_mesh"}, + {"cell_dimension", 2}, {"file", "In case you ever name your file like that: What is wrong with you?"}}; std::map files; CHECK_THROWS(wmtk::components::input(component_json, files)); } +} + +TEST_CASE("component_input_point", "[components][input][.]") +{ + json component_json = { + {"type", "input"}, + {"name", "input_mesh"}, + {"cell_dimension", 0}, + {"file", data_dir / "bunny_points.obj"}}; + + std::map files; + + CHECK_NOTHROW(wmtk::components::input(component_json, files)); } \ No newline at end of file diff --git a/tests/components/test_component_isotropic_remeshing.cpp b/tests/components/test_component_isotropic_remeshing.cpp index dfcb8be8ad..3ee561e187 100644 --- a/tests/components/test_component_isotropic_remeshing.cpp +++ b/tests/components/test_component_isotropic_remeshing.cpp @@ -32,9 +32,11 @@ TEST_CASE("smoothing_bunny", "[components][isotropic_remeshing][2D]") // input { - json input_component_json = {{"type", "input"}, - {"name", "input_mesh"}, - {"file", data_dir / "bunny.off"}}; + json input_component_json = { + {"type", "input"}, + {"name", "input_mesh"}, + {"cell_dimension", 2}, + {"file", data_dir / "bunny.off"}}; wmtk::components::input(input_component_json, files); } @@ -137,9 +139,18 @@ TEST_CASE("tangential_smoothing", "[components][isotropic_remeshing][2D]") Tuple v4 = mesh.tuple_from_id(PrimitiveType::Vertex, 4); Eigen::Vector3d p_init; - SECTION("1_0_1") { p_init = Eigen::Vector3d{1, 0, 1}; } - SECTION("0.5_0.5_1") { p_init = Eigen::Vector3d{0.5, 0.5, 1}; } - SECTION("0_0_7") { p_init = Eigen::Vector3d{0, 0, 7}; } + SECTION("1_0_1") + { + p_init = Eigen::Vector3d{1, 0, 1}; + } + SECTION("0.5_0.5_1") + { + p_init = Eigen::Vector3d{0.5, 0.5, 1}; + } + SECTION("0_0_7") + { + p_init = Eigen::Vector3d{0, 0, 7}; + } pos.vector_attribute(v4) = p_init; @@ -172,9 +183,18 @@ TEST_CASE("tangential_smoothing_boundary", "[components][isotropic_remeshing][2D Tuple v1 = mesh.tuple_from_id(PrimitiveType::Vertex, 1); Eigen::Vector3d p_init; - SECTION("1.7_1.1_0") { p_init = Eigen::Vector3d{1.7, 1.1, 0}; } - SECTION("2.2_2_0") { p_init = Eigen::Vector3d{2.2, 2, 0}; } - SECTION("2.2_2_5") { p_init = Eigen::Vector3d{2.2, 2, 5}; } + SECTION("1.7_1.1_0") + { + p_init = Eigen::Vector3d{1.7, 1.1, 0}; + } + SECTION("2.2_2_0") + { + p_init = Eigen::Vector3d{2.2, 2, 0}; + } + SECTION("2.2_2_5") + { + p_init = Eigen::Vector3d{2.2, 2, 5}; + } pos.vector_attribute(v1) = p_init; @@ -538,19 +558,22 @@ TEST_CASE("component_isotropic_remeshing", "[components][isotropic_remeshing][2D { std::map files; { - json input_component_json = {{"type", "input"}, - {"name", "input_mesh"}, - {"file", data_dir / "bunny.off"}}; + json input_component_json = { + {"type", "input"}, + {"name", "input_mesh"}, + {"cell_dimension", 2}, + {"file", data_dir / "bunny.off"}}; REQUIRE_NOTHROW(wmtk::components::input(input_component_json, files)); } - json mesh_isotropic_remeshing_json = {{"type", "isotropic_remeshing"}, - {"input", "input_mesh"}, - {"output", "output_mesh"}, - {"length_abs", 0.003}, - {"length_rel", -1}, - {"iterations", 1}, - {"lock_boundary", true}}; + json mesh_isotropic_remeshing_json = { + {"type", "isotropic_remeshing"}, + {"input", "input_mesh"}, + {"output", "output_mesh"}, + {"length_abs", 0.003}, + {"length_rel", -1}, + {"iterations", 1}, + {"lock_boundary", true}}; REQUIRE_NOTHROW(wmtk::components::isotropic_remeshing(mesh_isotropic_remeshing_json, files)); //{ diff --git a/tests/components/test_component_mesh_info.cpp b/tests/components/test_component_mesh_info.cpp index 63e7255c22..21f4adcdc2 100644 --- a/tests/components/test_component_mesh_info.cpp +++ b/tests/components/test_component_mesh_info.cpp @@ -14,6 +14,7 @@ TEST_CASE("component_mesh_info", "[components][mesh_info][.]") json input_component_json = { {"type", "input"}, {"name", "input_mesh"}, + {"cell_dimension", 2}, {"file", data_dir / "bunny.off"}}; diff --git a/tests/components/test_component_output.cpp b/tests/components/test_component_output.cpp index 8e29e0ff9d..76f44b1498 100644 --- a/tests/components/test_component_output.cpp +++ b/tests/components/test_component_output.cpp @@ -14,13 +14,18 @@ TEST_CASE("component_output", "[components][output][.]") json input_component_json = { {"type", "input"}, {"name", "input_mesh"}, + {"cell_dimension", 2}, {"file", data_dir / "bunny.off"}}; wmtk::components::input(input_component_json, files); SECTION("should pass") { - json component_json = {{"type", "output"}, {"input", "input_mesh"}, {"file", "bunny"}}; + json component_json = { + {"type", "output"}, + {"input", "input_mesh"}, + {"cell_dimension", 2}, + {"file", "bunny"}}; CHECK_NOTHROW(wmtk::components::output(component_json, files)); } @@ -30,6 +35,7 @@ TEST_CASE("component_output", "[components][output][.]") json component_json = { {"type", "output"}, {"input", "input_mesh"}, + {"cell_dimension", 2}, {"file", "unknown file ending.abcdef"}}; CHECK_THROWS(wmtk::components::output(component_json, files)); diff --git a/tests/test_simplex_collection.cpp b/tests/test_simplex_collection.cpp index eaa396ce60..af2c9a2b31 100644 --- a/tests/test_simplex_collection.cpp +++ b/tests/test_simplex_collection.cpp @@ -5,14 +5,14 @@ #include #include #include -#include -#include #include #include #include #include #include #include +#include +#include #include "tools/DEBUG_TriMesh.hpp" #include "tools/TriMesh_examples.hpp" @@ -23,6 +23,18 @@ constexpr PrimitiveType PV = PrimitiveType::Vertex; constexpr PrimitiveType PE = PrimitiveType::Edge; constexpr PrimitiveType PF = PrimitiveType::Face; constexpr PrimitiveType PT = PrimitiveType::Tetrahedron; +namespace { +template // use a DEBUG mesh type +void check_match_below_simplex_type(const MeshType& mesh, const Simplex& a, const Simplex& b) +{ + PrimitiveType min_type = std::min(a.primitive_type(), b.primitive_type()); + + for (int i = 0; i <= get_simplex_dimension(min_type); ++i) { + PrimitiveType cur_primitive_type = static_cast(i); + CHECK(mesh.id(a.tuple(), cur_primitive_type) == mesh.id(b.tuple(), cur_primitive_type)); + } +} +} // namespace TEST_CASE("simplex_comparison", "[simplex_collection][2D]") { @@ -165,25 +177,25 @@ TEST_CASE("simplex_boundary_iterable", "[simplex_collection][2D]") { tests::DEBUG_TriMesh m = tests::single_triangle(); - std::unique_ptr ptr_simplex; + Simplex simplex = Simplex::vertex({}); const Tuple t = m.edge_tuple_between_v1_v2(0, 1, 0); SECTION("vertex") { - ptr_simplex = std::make_unique(Simplex::vertex(t)); + simplex = Simplex::vertex(t); } SECTION("edge") { - ptr_simplex = std::make_unique(Simplex::edge(t)); + simplex = Simplex::edge(t); } SECTION("face") { - ptr_simplex = std::make_unique(Simplex::face(t)); + simplex = Simplex::face(t); } - SimplexBoundaryIterable itrb = simplex_boundary_iterable(m, *ptr_simplex); - SimplexCollection coll = simplex_boundary(m, *ptr_simplex); + SimplexBoundaryIterable itrb = simplex_boundary_iterable(m, simplex); + SimplexCollection coll = simplex_boundary(m, simplex); SimplexCollection itrb_collection(m); for (const Simplex& s : itrb) { @@ -198,15 +210,15 @@ TEST_CASE("simplex_boundary_iterable", "[simplex_collection][2D]") } } -TEST_CASE("simplex_coface_cells", "[simplex_collection][2D]") +TEST_CASE("simplex_top_level_cofaces", "[simplex_collection][2D]") { tests::DEBUG_TriMesh m = tests::hex_plus_two(); SECTION("vertex_interior") { const Tuple t = m.edge_tuple_between_v1_v2(4, 5, 2); - - SimplexCollection cc = coface_cells(m, simplex::Simplex::vertex(t)); + const simplex::Simplex input = simplex::Simplex::vertex(t); + SimplexCollection cc = top_level_cofaces(m, input); REQUIRE(cc.simplex_vector().size() == 6); REQUIRE(cc.simplex_vector(PrimitiveType::Face).size() == 6); @@ -218,12 +230,16 @@ TEST_CASE("simplex_coface_cells", "[simplex_collection][2D]") CHECK(m.id(cells[3]) == 5); CHECK(m.id(cells[4]) == 6); CHECK(m.id(cells[5]) == 7); + + for (const Simplex& s : cells) { + check_match_below_simplex_type(m, input, s); + } } SECTION("vertex_boundary") { const Tuple t = m.edge_tuple_between_v1_v2(3, 4, 0); - - SimplexCollection cc = coface_cells(m, simplex::Simplex::vertex(t)); + Simplex input = simplex::Simplex::vertex(t); + SimplexCollection cc = top_level_cofaces(m, input); REQUIRE(cc.simplex_vector().size() == 2); REQUIRE(cc.simplex_vector(PrimitiveType::Face).size() == 2); @@ -231,12 +247,16 @@ TEST_CASE("simplex_coface_cells", "[simplex_collection][2D]") const auto& cells = cc.simplex_vector(); CHECK(m.id(cells[0]) == 0); CHECK(m.id(cells[1]) == 5); + for (const Simplex& s : cells) { + check_match_below_simplex_type(m, input, s); + } } SECTION("edge_interior") { const Tuple t = m.edge_tuple_between_v1_v2(4, 5, 2); - SimplexCollection cc = coface_cells(m, simplex::Simplex::edge(t)); + Simplex input = simplex::Simplex::edge(t); + SimplexCollection cc = top_level_cofaces(m, input); REQUIRE(cc.simplex_vector().size() == 2); REQUIRE(cc.simplex_vector(PrimitiveType::Face).size() == 2); @@ -244,67 +264,78 @@ TEST_CASE("simplex_coface_cells", "[simplex_collection][2D]") const auto& cells = cc.simplex_vector(); CHECK(m.id(cells[0]) == 2); CHECK(m.id(cells[1]) == 7); + for (const Simplex& s : cells) { + check_match_below_simplex_type(m, input, s); + } } SECTION("edge_boundary") { const Tuple t = m.edge_tuple_between_v1_v2(3, 7, 5); - SimplexCollection cc = coface_cells(m, simplex::Simplex::edge(t)); + Simplex input = simplex::Simplex::edge(t); + SimplexCollection cc = top_level_cofaces(m, input); REQUIRE(cc.simplex_vector().size() == 1); REQUIRE(cc.simplex_vector(PrimitiveType::Face).size() == 1); const auto& cells = cc.simplex_vector(); CHECK(m.id(cells[0]) == 5); + for (const Simplex& s : cells) { + check_match_below_simplex_type(m, input, s); + } } SECTION("face") { const Tuple t = m.edge_tuple_between_v1_v2(4, 5, 2); - SimplexCollection cc = coface_cells(m, simplex::Simplex::face(t)); + Simplex input = simplex::Simplex::face(t); + SimplexCollection cc = top_level_cofaces(m, input); REQUIRE(cc.simplex_vector().size() == 1); REQUIRE(cc.simplex_vector(PrimitiveType::Face).size() == 1); const auto& cells = cc.simplex_vector(); CHECK(m.id(cells[0]) == 2); + for (const Simplex& s : cells) { + check_match_below_simplex_type(m, input, s); + } } } -TEST_CASE("simplex_coface_cells_iterable", "[simplex_collection][2D]") +TEST_CASE("simplex_top_level_cofaces_iterable", "[simplex_collection][2D]") { tests::DEBUG_TriMesh m = tests::hex_plus_two(); - std::unique_ptr ptr_simplex; + Simplex simplex = Simplex::vertex({}); SECTION("vertex_interior") { const Tuple t = m.edge_tuple_between_v1_v2(4, 5, 2); - ptr_simplex = std::make_unique(Simplex::vertex(t)); + simplex = Simplex::vertex(t); } SECTION("vertex_boundary") { const Tuple t = m.edge_tuple_between_v1_v2(3, 4, 0); - ptr_simplex = std::make_unique(Simplex::vertex(t)); + simplex = Simplex::vertex(t); } SECTION("edge_interior") { const Tuple t = m.edge_tuple_between_v1_v2(4, 5, 2); - ptr_simplex = std::make_unique(Simplex::edge(t)); + simplex = Simplex::edge(t); } SECTION("edge_boundary") { const Tuple t = m.edge_tuple_between_v1_v2(3, 7, 5); - ptr_simplex = std::make_unique(Simplex::edge(t)); + simplex = Simplex::edge(t); } SECTION("face") { const Tuple t = m.edge_tuple_between_v1_v2(4, 5, 2); - ptr_simplex = std::make_unique(Simplex::face(t)); + simplex = Simplex::face(t); } - CofaceCellsIterable itrb = coface_cells_iterable(m, *ptr_simplex); - SimplexCollection coll = coface_cells(m, *ptr_simplex); + TopLevelCofacesIterable itrb = top_level_cofaces_iterable(m, simplex); + SimplexCollection coll = top_level_cofaces(m, simplex); SimplexCollection itrb_collection(m); for (const Simplex& s : itrb) { @@ -315,7 +346,12 @@ TEST_CASE("simplex_coface_cells_iterable", "[simplex_collection][2D]") REQUIRE(itrb_collection.simplex_vector().size() == coll.simplex_vector().size()); for (size_t i = 0; i < coll.simplex_vector().size(); ++i) { - CHECK(m.simplices_are_equal(itrb_collection.simplex_vector()[i], coll.simplex_vector()[i])); + const Simplex& irtb_s = itrb_collection.simplex_vector()[i]; + const Simplex& coll_s = coll.simplex_vector()[i]; + + check_match_below_simplex_type(m, simplex, coll_s); + + CHECK(m.simplices_are_equal(irtb_s, coll_s)); } } @@ -429,36 +465,36 @@ TEST_CASE("simplex_open_star_iterable", "[simplex_collection][2D]") { tests::DEBUG_TriMesh m = tests::hex_plus_two(); - std::unique_ptr ptr_simplex; + Simplex simplex = Simplex::vertex({}); SECTION("vertex_interior") { const Tuple t = m.edge_tuple_between_v1_v2(4, 5, 2); - ptr_simplex = std::make_unique(Simplex::vertex(t)); + simplex = Simplex::vertex(t); } SECTION("vertex_boundary") { const Tuple t = m.edge_tuple_between_v1_v2(3, 4, 0); - ptr_simplex = std::make_unique(Simplex::vertex(t)); + simplex = Simplex::vertex(t); } SECTION("edge_interior") { const Tuple t = m.edge_tuple_between_v1_v2(4, 5, 2); - ptr_simplex = std::make_unique(Simplex::edge(t)); + simplex = Simplex::edge(t); } SECTION("edge_boundary") { const Tuple t = m.edge_tuple_between_v1_v2(3, 7, 5); - ptr_simplex = std::make_unique(Simplex::edge(t)); + simplex = Simplex::edge(t); } SECTION("face") { const Tuple t = m.edge_tuple_between_v1_v2(4, 5, 2); - ptr_simplex = std::make_unique(Simplex::face(t)); + simplex = Simplex::face(t); } - OpenStarIterable itrb = open_star_iterable(m, *ptr_simplex); - SimplexCollection coll = open_star(m, *ptr_simplex); + OpenStarIterable itrb = open_star_iterable(m, simplex); + SimplexCollection coll = open_star(m, simplex); SimplexCollection itrb_collection(m); for (const Simplex& s : itrb) { @@ -634,36 +670,36 @@ TEST_CASE("simplex_closed_star_iterable", "[simplex_collection][2D]") { tests::DEBUG_TriMesh m = tests::hex_plus_two(); - std::unique_ptr ptr_simplex; + Simplex simplex = Simplex::vertex({}); SECTION("vertex_interior") { const Tuple t = m.edge_tuple_between_v1_v2(4, 5, 2); - ptr_simplex = std::make_unique(Simplex::vertex(t)); + simplex = Simplex::vertex(t); } SECTION("vertex_boundary") { const Tuple t = m.edge_tuple_between_v1_v2(3, 4, 0); - ptr_simplex = std::make_unique(Simplex::vertex(t)); + simplex = Simplex::vertex(t); } SECTION("edge_interior") { const Tuple t = m.edge_tuple_between_v1_v2(4, 5, 2); - ptr_simplex = std::make_unique(Simplex::edge(t)); + simplex = Simplex::edge(t); } SECTION("edge_boundary") { const Tuple t = m.edge_tuple_between_v1_v2(3, 7, 5); - ptr_simplex = std::make_unique(Simplex::edge(t)); + simplex = Simplex::edge(t); } SECTION("face") { const Tuple t = m.edge_tuple_between_v1_v2(4, 5, 2); - ptr_simplex = std::make_unique(Simplex::face(t)); + simplex = Simplex::face(t); } - ClosedStarIterable itrb = closed_star_iterable(m, *ptr_simplex); - SimplexCollection coll = closed_star(m, *ptr_simplex); + ClosedStarIterable itrb = closed_star_iterable(m, simplex); + SimplexCollection coll = closed_star(m, simplex); SimplexCollection itrb_collection(m); for (const Simplex& s : itrb) { @@ -776,36 +812,36 @@ TEST_CASE("simplex_link_iterable", "[simplex_collection][2D]") { tests::DEBUG_TriMesh m = tests::hex_plus_two(); - std::unique_ptr ptr_simplex; + Simplex simplex = Simplex::vertex({}); SECTION("vertex_interior") { const Tuple t = m.edge_tuple_between_v1_v2(4, 5, 2); - ptr_simplex = std::make_unique(Simplex::vertex(t)); + simplex = Simplex::vertex(t); } SECTION("vertex_boundary") { const Tuple t = m.edge_tuple_between_v1_v2(3, 4, 0); - ptr_simplex = std::make_unique(Simplex::vertex(t)); + simplex = Simplex::vertex(t); } SECTION("edge_interior") { const Tuple t = m.edge_tuple_between_v1_v2(4, 5, 2); - ptr_simplex = std::make_unique(Simplex::edge(t)); + simplex = Simplex::edge(t); } SECTION("edge_boundary") { const Tuple t = m.edge_tuple_between_v1_v2(3, 7, 5); - ptr_simplex = std::make_unique(Simplex::edge(t)); + simplex = Simplex::edge(t); } SECTION("face") { const Tuple t = m.edge_tuple_between_v1_v2(4, 5, 2); - ptr_simplex = std::make_unique(Simplex::face(t)); + simplex = Simplex::face(t); } - LinkIterable itrb = link_iterable(m, *ptr_simplex); - SimplexCollection coll = link(m, *ptr_simplex); + LinkIterable itrb = link_iterable(m, simplex); + SimplexCollection coll = link(m, simplex); SimplexCollection itrb_collection(m); for (const Simplex& s : itrb) { @@ -818,4 +854,4 @@ TEST_CASE("simplex_link_iterable", "[simplex_collection][2D]") for (size_t i = 0; i < coll.simplex_vector().size(); ++i) { CHECK(m.simplices_are_equal(itrb_collection.simplex_vector()[i], coll.simplex_vector()[i])); } -} \ No newline at end of file +} diff --git a/tests/tools/DEBUG_TetMesh.cpp b/tests/tools/DEBUG_TetMesh.cpp index 426f2d8bdc..d8b5df2bf0 100644 --- a/tests/tools/DEBUG_TetMesh.cpp +++ b/tests/tools/DEBUG_TetMesh.cpp @@ -1,6 +1,6 @@ #include "DEBUG_TetMesh.hpp" #include -#include +#include namespace wmtk::tests_3d { @@ -43,10 +43,10 @@ auto DEBUG_TetMesh::edge_tuple_between_v1_v2(const long v1, const long v2, const long local_eid = -1; for (long i = 0; i < 6; ++i) { - if ((wmtk::autogen::auto_3d_edges[i][0] == local_vid1 && - wmtk::autogen::auto_3d_edges[i][1] == local_vid2) || - (wmtk::autogen::auto_3d_edges[i][0] == local_vid2 && - wmtk::autogen::auto_3d_edges[i][1] == local_vid1)) { + if ((wmtk::autogen::tet_mesh::auto_3d_edges[i][0] == local_vid1 && + wmtk::autogen::tet_mesh::auto_3d_edges[i][1] == local_vid2) || + (wmtk::autogen::tet_mesh::auto_3d_edges[i][0] == local_vid2 && + wmtk::autogen::tet_mesh::auto_3d_edges[i][1] == local_vid1)) { local_eid = i; break; } @@ -54,7 +54,7 @@ auto DEBUG_TetMesh::edge_tuple_between_v1_v2(const long v1, const long v2, const assert(local_eid > -1); - long local_fid = wmtk::autogen::auto_3d_table_complete_edge[local_eid][2]; + long local_fid = wmtk::autogen::tet_mesh::auto_3d_table_complete_edge[local_eid][2]; assert(local_fid > -1); return Tuple(local_vid1, local_eid, local_fid, tid, 0); @@ -86,10 +86,10 @@ auto DEBUG_TetMesh::edge_tuple_between_v1_v2( long local_eid = -1; for (long i = 0; i < 6; ++i) { - if ((wmtk::autogen::auto_3d_edges[i][0] == local_vid1 && - wmtk::autogen::auto_3d_edges[i][1] == local_vid2) || - (wmtk::autogen::auto_3d_edges[i][0] == local_vid2 && - wmtk::autogen::auto_3d_edges[i][1] == local_vid1)) { + if ((wmtk::autogen::tet_mesh::auto_3d_edges[i][0] == local_vid1 && + wmtk::autogen::tet_mesh::auto_3d_edges[i][1] == local_vid2) || + (wmtk::autogen::tet_mesh::auto_3d_edges[i][0] == local_vid2 && + wmtk::autogen::tet_mesh::auto_3d_edges[i][1] == local_vid1)) { local_eid = i; break; } @@ -102,9 +102,9 @@ auto DEBUG_TetMesh::edge_tuple_between_v1_v2( std::sort(sorted_local_vids.begin(), sorted_local_vids.end()); for (long i = 0; i < 4; ++i) { - if (wmtk::autogen::auto_3d_faces[i][0] == sorted_local_vids[0] && - wmtk::autogen::auto_3d_faces[i][1] == sorted_local_vids[1] && - wmtk::autogen::auto_3d_faces[i][2] == sorted_local_vids[2]) { + if (wmtk::autogen::tet_mesh::auto_3d_faces[i][0] == sorted_local_vids[0] && + wmtk::autogen::tet_mesh::auto_3d_faces[i][1] == sorted_local_vids[1] && + wmtk::autogen::tet_mesh::auto_3d_faces[i][2] == sorted_local_vids[2]) { local_fid = i; break; } @@ -138,10 +138,10 @@ auto DEBUG_TetMesh::edge_tuple_from_vids(const long v1, const long v2) const -> long local_eid = -1; for (long i = 0; i < 6; ++i) { - if ((wmtk::autogen::auto_3d_edges[i][0] == local_vid1 && - wmtk::autogen::auto_3d_edges[i][1] == local_vid2) || - (wmtk::autogen::auto_3d_edges[i][0] == local_vid2 && - wmtk::autogen::auto_3d_edges[i][1] == local_vid1)) { + if ((wmtk::autogen::tet_mesh::auto_3d_edges[i][0] == local_vid1 && + wmtk::autogen::tet_mesh::auto_3d_edges[i][1] == local_vid2) || + (wmtk::autogen::tet_mesh::auto_3d_edges[i][0] == local_vid2 && + wmtk::autogen::tet_mesh::auto_3d_edges[i][1] == local_vid1)) { local_eid = i; break; } @@ -149,10 +149,10 @@ auto DEBUG_TetMesh::edge_tuple_from_vids(const long v1, const long v2) const -> assert(local_eid > -1); - long local_fid = wmtk::autogen::auto_3d_table_complete_edge[local_eid][2]; + long local_fid = wmtk::autogen::tet_mesh::auto_3d_table_complete_edge[local_eid][2]; assert(local_fid > -1); - long local_vid = wmtk::autogen::auto_3d_table_complete_edge[local_eid][0]; + long local_vid = wmtk::autogen::tet_mesh::auto_3d_table_complete_edge[local_eid][0]; return Tuple(local_vid, local_eid, local_fid, tid, 0); } @@ -188,9 +188,9 @@ auto DEBUG_TetMesh::face_tuple_from_vids(const long v1, const long v2, const lon std::sort(sorted_local_vids.begin(), sorted_local_vids.end()); for (long i = 0; i < 4; ++i) { - if (wmtk::autogen::auto_3d_faces[i][0] == sorted_local_vids[0] && - wmtk::autogen::auto_3d_faces[i][1] == sorted_local_vids[1] && - wmtk::autogen::auto_3d_faces[i][2] == sorted_local_vids[2]) { + if (wmtk::autogen::tet_mesh::auto_3d_faces[i][0] == sorted_local_vids[0] && + wmtk::autogen::tet_mesh::auto_3d_faces[i][1] == sorted_local_vids[1] && + wmtk::autogen::tet_mesh::auto_3d_faces[i][2] == sorted_local_vids[2]) { local_fid = i; break; } @@ -198,10 +198,10 @@ auto DEBUG_TetMesh::face_tuple_from_vids(const long v1, const long v2, const lon assert(local_fid > -1); - long local_eid = wmtk::autogen::auto_3d_table_complete_face[local_fid][1]; + long local_eid = wmtk::autogen::tet_mesh::auto_3d_table_complete_face[local_fid][1]; assert(local_eid > -1); - long local_vid = wmtk::autogen::auto_3d_table_complete_face[local_fid][0]; + long local_vid = wmtk::autogen::tet_mesh::auto_3d_table_complete_face[local_fid][0]; return Tuple(local_vid, local_eid, local_fid, tid, 0); }