diff --git a/scripts/2d_switch_tables.ipynb b/scripts/2d_switch_tables.ipynb index 81116cceb8..e1fe353b61 100644 --- a/scripts/2d_switch_tables.ipynb +++ b/scripts/2d_switch_tables.ipynb @@ -244,7 +244,7 @@ "metadata": {}, "outputs": [], "source": [ - "autogenerate(\"../src/wmtk/autogen/tri_mesh/autogenerated_tables.{}pp\", tri_data)" + "autogenerate([\"autogenerated_data\"], tri_data)" ] }, { @@ -271,7 +271,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/scripts/3d_switch_tables.ipynb b/scripts/3d_switch_tables.ipynb index 79a16118d2..f265558c75 100644 --- a/scripts/3d_switch_tables.ipynb +++ b/scripts/3d_switch_tables.ipynb @@ -682,7 +682,7 @@ "metadata": {}, "outputs": [], "source": [ - "autogenerate(\"../src/wmtk/autogen/tet_mesh/autogenerated_tables.{}pp\", tet_data)" + "autogenerate([\"autogenerated_data\"], tet_data)" ] }, { @@ -709,9 +709,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.12.3" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/scripts/SimplexComplex.py b/scripts/SimplexComplex.py new file mode 100644 index 0000000000..d398bcb95c --- /dev/null +++ b/scripts/SimplexComplex.py @@ -0,0 +1,164 @@ +from itertools import product + +class SimplexComplex: + def __init__(self, simplices): + self.__simplices__ = list(map(lambda x: list(map(frozenset,x)), simplices)) + + self.__valid_indices__ = [self.get_index(t) for t in self.all_tuples() if self.valid_tuple(t)] + self.__valid_index_map__ = {k:v for v,k in enumerate(self.__valid_indices__)} + + def __getitem__(self, index): + return self.__simplices__.__getitem__(index) +# Generates all possible tuples, note that some might not be valid + def all_tuples(self): + r = list(product(*map(list,map(range,map(len,self.__simplices__))))) + return r + + def valid_indices(self): + return self.__valid_indices__ + # Check if a tuple is valid, i.e. if the simplex of dimension d-1 is a face of a simplex of dimension d + def valid_tuple(self,t): + items = tuple(self[i][t[i]] for i in range(len(t))) + return all(a.issubset(b) for a,b in zip(items[:-1],items[1:])) + + def valid_tuple_as_simplicial_set(self,t): + assert(self.valid_tuple(t)) + items = tuple(self[i][t[i]] for i in range(len(t))) + x = (next(iter(items[0])),) + tuple(next(iter((b-a))) for a,b in zip(items[:-1],items[1:])) + + n = len(self) + return x + (int((n * (n+1)) / 2) - sum(x),) + + def simplicial_set_as_valid_tuple(self, ss): + + + + return tuple(self.__simplices__[d].index(frozenset(ss[:d+1])) + for d in range(len(ss)-1)) + + def simplicial_set_as_valid_tuple_index(self,ss): + tup = self.simplicial_set_as_valid_tuple(ss) + return self.valid_tuples().index(tup) + + + def __len__(self): + return self.__simplices__.__len__() + + # Enumerates all valid tuples similar to t, but with a different value in the slot d + # There must be 2 of them, and this function returns the one that is different than t + def switch(self,t,d): + assert(self.valid_tuple(t)) + t = tuple(t) + candidates = [] + left = t[:d] + right = t[d+1:] + candidates = [left + (i,) + right for i in range(len(self[d])) if i != t[d]] + valid = [x for x in candidates if self.valid_tuple(x)] + assert(len(valid) == 1) + return valid[0] + + + def get_index(self, t): + assert(self.valid_tuple(t)) + return self.all_tuples().index(t) + + def tuple_from_index(self,index): + return self.all_tuples()[index] + + def valid_tuple_index(self,index): + return self.tuple_from_index(self.__valid_indices__[index]) + + def valid_tuple_size(self): + return len(self.__valid_indices__) + + def valid_tuple_index(self, index): + return self.__valid_indices__[index] + + + def index_switch(self,tuple_index, d): + return self.get_index(self.switch(self.tuple_from_index(tuple_index), d)) + def valid_index_switch(self,tuple_index, d): + return self.__valid_index_map__[ + self.index_switch( + self.__valid_indices__[tuple_index], d) + ] + + def valid_tuples(self): + ts = self.all_tuples() + return [ + ts[j] for j in self.__valid_indices__ + ] + + def valid_tuple_product(self, t1, t2): + s1 = self.valid_tuple_as_simplicial_set(t1) + s2 = self.valid_tuple_as_simplicial_set(t2) + + sp = tuple(s1[i] for i in s2) + + return self.simplicial_set_as_valid_tuple(sp) + + def valid_tuple_index_product(self, i1, i2): + vt = self.valid_tuples() + return vt.index(self.valid_tuple_product( + vt[i1], + vt[i2] + )) + + +def valid_switch_table(sc): + return [[sc.valid_index_switch(i,d) for d in range(len(sc))] for i in range(sc.valid_tuple_size())] + + +def valid_switch_product_table(sc): + size = sc.valid_tuple_size() + return [[sc.valid_tuple_index_product(i1,i2) for i2 in range(size)] for i1 in range(size)] + +def valid_switch_inverse_table(sc): + table = valid_switch_product_table(sc) + size = sc.valid_tuple_size() + identity_valid_index = sc.simplicial_set_as_valid_tuple_index(tuple(range(len(sc)+1))) + return [table[i].index(identity_valid_index) for i in range(size)] + + +def switches_plus_identity(sc): + identity = tuple(range(len(sc)+1)) + print("Identity: ", identity) + def s(i): + x = list(identity) + print("1:",x) + x[i],x[i+1] = x[i+1],x[i] + print("2:",x) + return tuple(x) + sss = tuple(s(i) for i in range(len(sc))) + (identity,) + print(sss) + return tuple(map(sc.simplicial_set_as_valid_tuple_index,sss)) + + +def switch_normal_subgroup_table(sc, subgroup_sc): + assert(len(sc) >= len(subgroup_sc)) + + valid_tuples = sc.valid_tuples() + valid_subtuples = subgroup_sc.valid_tuples() + tail = tuple(range(len(subgroup_sc)+1,len(sc)+1)) + + subgroup_to_group = [-1 for _ in range(subgroup_sc.valid_tuple_size())] + group_to_subgroup = [-1 for _ in range(sc.valid_tuple_size())] + + for subindex, subtup in enumerate(valid_subtuples): + sub_ss = subgroup_sc.valid_tuple_as_simplicial_set(subtup) + ss = sub_ss + tail + + index = sc.simplicial_set_as_valid_tuple_index(ss) + subgroup_to_group[subindex] = index + group_to_subgroup[index] = subindex + + pass + + + assert(all(x != -1 for x in subgroup_to_group)) + + return tuple(group_to_subgroup),tuple(subgroup_to_group) + + + + diff --git a/scripts/autogenerate.py b/scripts/autogenerate.py index 2b471786fe..09a8842594 100644 --- a/scripts/autogenerate.py +++ b/scripts/autogenerate.py @@ -23,7 +23,7 @@ # ] # } -def autogenerate(path_format, data): +def autogenerate(files, data, use_clang_format = False, clang_format_binary = "clang-format", autogen_path="../src/wmtk/autogen/"): environment = jinja2.Environment(loader=jinja2.FileSystemLoader("./")) @@ -38,18 +38,28 @@ def to_list_or_int(dat): 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) + def write(path, template): + with open(path,"w") as file: + file.write(template.render(data)) + if use_clang_format: + import subprocess + try: + subprocess.Popen([clang_format_binary,"-i",path]) + except FileNotFoundError: + print("Warning: autogenerate failed to run clang-format due to FileNotFoundError - please make sure the autogenerated files are properly formatted before committing them") + + for file in files: + data["filename"] = file + for extension in ("hpp","cpp","hxx"): + output_filename = f"{file}.{extension}" + template_path = os.path.join("templates",output_filename + ".template") + if os.path.exists(template_path): + template = environment.get_template(template_path) + output_path = os.path.join(autogen_path, data["namespace"], output_filename) + write(output_path, template) + @@ -70,4 +80,4 @@ def write(char,template): ] } - autogenerate("/tmp/test.{}pp", array_data) + autogenerate(["autogenerated_tables"], array_data, autogen_path="/tmp") diff --git a/scripts/generate.ipynb b/scripts/generate.ipynb new file mode 100644 index 0000000000..8aa53c3da8 --- /dev/null +++ b/scripts/generate.ipynb @@ -0,0 +1,324 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "bb6d9708-eb30-4908-9dfd-9acca5079239", + "metadata": {}, + "outputs": [], + "source": [ + "import autogenerate\n", + "import importlib\n", + "importlib.reload(autogenerate)\n", + "autogenerate = autogenerate.autogenerate\n", + "import SimplexComplex as SC" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "5daf8d4a-135f-4ebf-942a-1a581cd5696c", + "metadata": {}, + "outputs": [], + "source": [ + "active_tables = [\"autogenerated_tables\",\"SimplexDart\",\"valid_index_from_tuple\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "8d72e118-5eee-43bb-a889-69ca4cd5d051", + "metadata": {}, + "outputs": [], + "source": [ + "def list_pair_to_array(data, name, comment = None, type_name=\"int64_t\"):\n", + " r = {\"name\": name, \"data\": data, \"type\": type_name}\n", + " if comment is not None: r[\"comment\"] = comment\n", + " return r" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "9da94306", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "def get_switch_data(sc):\n", + " valid_indices = sc.valid_indices()\n", + " all_to_valid = [-1 for _ in sc.all_tuples()]\n", + " for i,v in enumerate(valid_indices):\n", + " all_to_valid[v] = i\n", + " return [\n", + " list_pair_to_array(sc.valid_tuples(),\"auto_valid_tuples\", \"Valid tuple local indices\", type_name = \"int8_t\"),\n", + " list_pair_to_array(valid_indices,\"auto_valid_tuple_indices\", \"For each valid tuple encodes the raw tuple index\", type_name = \"int8_t\"),\n", + " list_pair_to_array(all_to_valid,\"auto_all_to_valid_tuple_indices\", \"Index of each tuple according to valid tuple indexing\", type_name = \"int8_t\"),\n", + "\n", + "list_pair_to_array(SC.valid_switch_table(sc),\"auto_valid_switch_table\", \"Valid tuple indices\", type_name = \"int8_t\"),\n", + "list_pair_to_array(SC.valid_switch_product_table(sc),\"auto_valid_switch_product_table\", \"Tuple group product using valid tuple indices\", type_name = \"int8_t\"),\n", + "list_pair_to_array(SC.valid_switch_inverse_table(sc),\"auto_valid_switch_inverse_table\", \"Tuple group product inverse using valid tuple indices\", type_name = \"int8_t\"),\n", + "list_pair_to_array(SC.switches_plus_identity(sc),\"auto_valid_tuple_switch_indices\", \"Which tuples are associated with switching. Last entry is the identity tuple\", type_name = \"int8_t\"),\n", + " ]" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "fc87f02b-58f4-4d63-8433-045b3281ebb3", + "metadata": {}, + "outputs": [], + "source": [ + "import switch_tables_2d as st2d\n", + "sc2 = st2d.simplex_complex" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "77a9a4e7-89cf-427f-8c5d-45ced96abe1d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Identity: (0, 1, 2)\n", + "1: [0, 1, 2]\n", + "2: [1, 0, 2]\n", + "1: [0, 1, 2]\n", + "2: [0, 2, 1]\n", + "((1, 0, 2), (0, 2, 1), (0, 1, 2))\n" + ] + } + ], + "source": [ + "tri_data = {\"namespace\": \"tri_mesh\", \"type\": \"Triangle\", \"tables\": [\n", + "list_pair_to_array(st2d.edges,\"auto_2d_edges\", \"lvids for a particular leid\"),\n", + "list_pair_to_array(st2d.table(0,st2d.simplices),\"auto_2d_table_vertex\", \"vertex switch's (tuple_index -> [lvid,leid])\"),\n", + "list_pair_to_array(st2d.table(1,st2d.simplices),\"auto_2d_table_edge\", \"edge switch's (tuple_index -> [lvid,leid])\"),\n", + "list_pair_to_array(st2d.table_ccw(st2d.simplices),\"auto_2d_table_ccw\", \"(tuple_index) -> is_ccw\"),\n", + "list_pair_to_array(st2d.table_complete_tuple(0,st2d.simplices),\"auto_2d_table_complete_vertex\", \"lvid -> a ccw [lvid,leid]\"),\n", + "list_pair_to_array(st2d.table_complete_tuple(1,st2d.simplices),\"auto_2d_table_complete_edge\", \"leid -> a ccw [lvid,leid]\"),\n", + "] + get_switch_data(sc2)}\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "3a0bb048-fa81-47e7-a695-be359e75fe78", + "metadata": {}, + "outputs": [], + "source": [ + "autogenerate(active_tables, tri_data, use_clang_format=True)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "b5a3326e-77f7-4ec5-9208-b5510261ef5d", + "metadata": {}, + "outputs": [], + "source": [ + "import switch_tables_3d as st3d\n", + "sc3 = st3d.simplex_complex" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "a2f8d408-651f-4b38-8a32-3dba93c63a24", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Identity: (0, 1, 2, 3)\n", + "1: [0, 1, 2, 3]\n", + "2: [1, 0, 2, 3]\n", + "1: [0, 1, 2, 3]\n", + "2: [0, 2, 1, 3]\n", + "1: [0, 1, 2, 3]\n", + "2: [0, 1, 3, 2]\n", + "((1, 0, 2, 3), (0, 2, 1, 3), (0, 1, 3, 2), (0, 1, 2, 3))\n" + ] + } + ], + "source": [ + "tet_data = {\"namespace\": \"tet_mesh\", \"type\": \"Tetrahedron\", \"tables\": [\n", + "list_pair_to_array(st3d.edges,\"auto_3d_edges\", \"lvids for a specfic leid\"),\n", + "list_pair_to_array(st3d.faces,\"auto_3d_faces\", \"lvids for a specific lfid\"),\n", + "list_pair_to_array(st3d.table(0,st3d.simplices),\"auto_3d_table_vertex\", \"vertex switch's (tuple_index -> [lvid,leid,lfid])\"),\n", + "list_pair_to_array(st3d.table(1,st3d.simplices),\"auto_3d_table_edge\", \"edge switch's (tuple_index -> [lvid,leid,lfid])\"),\n", + "list_pair_to_array(st3d.table(2,st3d.simplices),\"auto_3d_table_face\", \"face switch's (tuple_index -> [lvid,leid,lfid])\"),\n", + "list_pair_to_array(st3d.table_ccw(st3d.simplices),\"auto_3d_table_ccw\", \"(tuple_index) -> is_ccw\"),\n", + "list_pair_to_array(st3d.table_complete_tuple(0,st3d.simplices),\"auto_3d_table_complete_vertex\", \"lvid -> a ccw [lvid,leid,lfid]\"),\n", + "list_pair_to_array(st3d.table_complete_tuple(1,st3d.simplices),\"auto_3d_table_complete_edge\", \"evid -> a ccw [lvid,leid,lfid]\"),\n", + "list_pair_to_array(st3d.table_complete_tuple(2,st3d.simplices),\"auto_3d_table_complete_face\", \"fvid -> a ccw [lvid,leid,lfid]\")]\n", + " + get_switch_data(sc3)\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "36443fc2-668d-4ca7-a474-d451d728f684", + "metadata": {}, + "outputs": [], + "source": [ + "autogenerate(active_tables, tet_data, use_clang_format=True)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "9903a322-99be-448f-8d11-0a166e8f5683", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Identity: (0, 1)\n", + "1: [0, 1]\n", + "2: [1, 0]\n", + "((1, 0), (0, 1))\n" + ] + } + ], + "source": [ + "import switch_tables_1d as st1d\n", + "sc1 = st1d.simplex_complex\n", + "edge_data = {\"namespace\": \"edge_mesh\", \"type\": \"Edge\", \"tables\": \n", + "get_switch_data(sc1)\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "7b38a21f-b057-4b54-9bdb-425604ff3743", + "metadata": {}, + "outputs": [], + "source": [ + "autogenerate(active_tables,edge_data, use_clang_format=True)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "eaa4ec33-71f6-4918-a68e-5be4839127ce", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 0 1 1\n", + "0 1 1 2\n", + "0 2 1 3\n", + "1 0 2 1\n", + "1 1 2 2\n", + "1 2 2 3\n", + "2 0 3 1\n", + "2 1 3 2\n", + "2 2 3 3\n" + ] + } + ], + "source": [ + "scs = tuple((sc1,sc2,sc3))\n", + "data = [[None for _ in scs] for _ in scs]\n", + "autogen_tables = []\n", + "for r,a in enumerate(scs):\n", + " for c,b in enumerate(scs):\n", + " print(r,c,len(a),len(b))\n", + " if r < c:\n", + " continue\n", + " f,b = SC.switch_normal_subgroup_table(a,b)\n", + " autogen_tables.append({\"name\": f\"subgroup_indices_{r}_{c}\", \"data\": f, \"type\": \"int8_t\"})\n", + " if r != c:\n", + " autogen_tables.append({\"name\": f\"subgroup_indices_{c}_{r}\", \"data\": b, \"type\": \"int8_t\"})" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "7f131018-509c-4ec9-8291-ea59e16611b2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[{'name': 'subgroup_indices_0_0', 'data': (0, 1), 'type': 'int8_t'}, {'name': 'subgroup_indices_1_0', 'data': (-1, 0, -1, 1, -1, -1), 'type': 'int8_t'}, {'name': 'subgroup_indices_0_1', 'data': (1, 3), 'type': 'int8_t'}, {'name': 'subgroup_indices_1_1', 'data': (0, 1, 2, 3, 4, 5), 'type': 'int8_t'}, {'name': 'subgroup_indices_2_0', 'data': (-1, 0, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), 'type': 'int8_t'}, {'name': 'subgroup_indices_0_2', 'data': (1, 7), 'type': 'int8_t'}, {'name': 'subgroup_indices_2_1', 'data': (-1, 1, -1, 0, -1, -1, -1, 3, -1, 2, -1, -1, -1, 5, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1), 'type': 'int8_t'}, {'name': 'subgroup_indices_1_2', 'data': (3, 1, 9, 7, 15, 13), 'type': 'int8_t'}, {'name': 'subgroup_indices_2_2', 'data': (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23), 'type': 'int8_t'}]\n", + "{'namespace': 'subgroup', 'tables': [{'name': 'subgroup_indices_0_0', 'data': (0, 1), 'type': 'int8_t'}, {'name': 'subgroup_indices_1_0', 'data': (-1, 0, -1, 1, -1, -1), 'type': 'int8_t'}, {'name': 'subgroup_indices_0_1', 'data': (1, 3), 'type': 'int8_t'}, {'name': 'subgroup_indices_1_1', 'data': (0, 1, 2, 3, 4, 5), 'type': 'int8_t'}, {'name': 'subgroup_indices_2_0', 'data': (-1, 0, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), 'type': 'int8_t'}, {'name': 'subgroup_indices_0_2', 'data': (1, 7), 'type': 'int8_t'}, {'name': 'subgroup_indices_2_1', 'data': (-1, 1, -1, 0, -1, -1, -1, 3, -1, 2, -1, -1, -1, 5, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1), 'type': 'int8_t'}, {'name': 'subgroup_indices_1_2', 'data': (3, 1, 9, 7, 15, 13), 'type': 'int8_t'}, {'name': 'subgroup_indices_2_2', 'data': (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23), 'type': 'int8_t'}], 'dimensions': 3}\n" + ] + } + ], + "source": [ + "print(autogen_tables)\n", + "\n", + "\n", + "max_dim = max(map(len,scs))\n", + "\n", + "subgroup_data = {\"namespace\": \"subgroup\", \"tables\": autogen_tables, \"dimensions\": max_dim}\n", + "print(subgroup_data)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "8c238d63-daf6-4744-9d1f-8fb58dbfd4d9", + "metadata": {}, + "outputs": [], + "source": [ + "autogenerate([\"subgroup_transformations\"], subgroup_data, use_clang_format=True)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "18591bdf-5d7e-4ed6-8c63-1b3e716e1d61", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dbbaa1e2-93a3-4bc9-9dba-52ea8aadca37", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/scripts/switch_tables_1d.py b/scripts/switch_tables_1d.py new file mode 100644 index 0000000000..4d6e84f2c2 --- /dev/null +++ b/scripts/switch_tables_1d.py @@ -0,0 +1,12 @@ +# The index convenction is arbitrary, +# orientation is not important here +from SimplexComplex import SimplexComplex,valid_switch_table, valid_switch_product_table,valid_switch_inverse_table + + +vertices = [{0},{1}] + + +s = [vertices] +simplices = s + +simplex_complex = SimplexComplex(simplices) diff --git a/scripts/switch_tables_2d.py b/scripts/switch_tables_2d.py new file mode 100644 index 0000000000..f0051c0562 --- /dev/null +++ b/scripts/switch_tables_2d.py @@ -0,0 +1,106 @@ +# The index convenction is arbitrary, +# orientation is not important here +from SimplexComplex import SimplexComplex,valid_switch_table, valid_switch_product_table,valid_switch_inverse_table + + +vertices = [{0},{1},{2}] + +edges = [ + {1,2}, + {2,0}, + {0,1}, +] + +edges_oriented = [ + [1,2], + [2,0], + [0,1], +] + +s = [vertices,edges] +simplices = s + +simplex_complex = SimplexComplex(simplices) + + +# Generates all possible tuples, note that some might not be valid +def all_tuples(s): + return [[i,j] for i in range(len(s[0])) for j in range(len(s[1]))] + +# Check if a tuple is valid, i.e. if the simplex of dimension d-1 is a face of a simplex of dimension d +def valid_tuple(t,s): + return s[0][t[0]].issubset(s[1][t[1]]) + +# Check if a tuple is ccw +def ccw_tuple(t,s): + assert(valid_tuple(t,s)) + assert (edges_oriented[t[1]][0] in s[0][t[0]]) or (edges_oriented[t[1]][1] in s[0][t[0]]) + return edges_oriented[t[1]][0] in s[0][t[0]] + +# valid = [t for t in all_tuples(s) if valid_tuple(t,s)] + +# Enumerates all valid tuples similar to t, but with a different value in the slot d +# There must be 2 of them, and this function returns the one that is different than t +def switch(t,d,s): + candidates = [] + for i in range(len(s[d])): + t2 = t.copy() + t2[d] = i + candidates.append(t2) + valid = [x for x in candidates if valid_tuple(x,s)] + assert(len(valid) == 2) + valid.remove(t) + assert(len(valid) == 1) + return valid[0] + +# Builds a table for the switch operation of dimension d +def table(d,s): + # Generates a table for switch_vertex + sv = all_tuples(s) + + for i in range(len(sv)): + if not valid_tuple(sv[i],s): + sv[i] = [-1,-1] + else: + sv[i] = switch(sv[i],d,s) + + return sv + +# Builds a table for the switch operation of dimension d +def table_ccw(s): + # Generates a table for switch_vertex + sv = all_tuples(s) + out = [-1 for i in sv] + + for i in range(len(sv)): + if not valid_tuple(sv[i],s): + out[i] = -1 + else: + if ccw_tuple(sv[i],s): + out[i] = 1 + else: + out[i] = 0 + + return out + +# table_ccw("auto_2d_table_ccw",s) + +def table_complete_tuple(d,s): + # Generates a table for switch_vertex + sv = [t for t in all_tuples(s) if (valid_tuple(t,s) and ccw_tuple(t,s))] + out = [] + for c in range(len(s[d])): + for i in range(len(sv)): + if c == sv[i][d]: + out.append(sv[i]) + break + + assert(len(out) == len(s[d])) + + return out + +#table_complete_tuple("complete_vertex",0,s) + +def switch_index(i,d,s,table): + pass + \ No newline at end of file diff --git a/scripts/switch_tables_3d.py b/scripts/switch_tables_3d.py new file mode 100644 index 0000000000..1dc214003e --- /dev/null +++ b/scripts/switch_tables_3d.py @@ -0,0 +1,133 @@ +# The index convenction is arbitrary, +# orientation is not important here +from SimplexComplex import SimplexComplex,valid_switch_table, valid_switch_product_table,valid_switch_inverse_table + +vertices = [{0},{1},{2},{3}] + +edges = [ + {0,1}, + {0,2}, + {0,3}, + {1,2}, + {1,3}, + {2,3} +] + +faces = [ + {1,2,3}, + {0,3,2}, + {0,1,3}, + {0,2,1} + ] + +faces_oriented = [ + [1,2,3], + [0,3,2], + [0,1,3], + [0,2,1] + ] + + +s = [vertices,edges,faces] + + +simplices = s + +simplex_complex = SimplexComplex(simplices) +""" + +for t in simplex_complex.valid_tuples(): + + print(t, simplex_complex.valid_tuple_as_simplicial_set(t)) + print(t, simplex_complex.simplicial_set_as_valid_tuple(simplex_complex.valid_tuple_as_simplicial_set(t))) + +print(valid_switch_table(simplex_complex)) +print(valid_switch_product_table(simplex_complex)) +print(valid_switch_inverse_table(simplex_complex)) + +for a,b in enumerate(valid_switch_inverse_table(simplex_complex)): + print(a,b,simplex_complex.valid_tuple_index_product(a,b)) +""" + +# Generates all possible tuples, note that some might not be valid +def all_tuples(s): + return SimplexComplex(s).all_tuples() + + +# Check if a tuple is valid, i.e. if the simplex of dimension d-1 is a face of a simplex of dimension d +def valid_tuple(t,s): + return SimplexComplex(s).valid_tuple(t) + + +# Check if a tuple is ccw +def ccw_tuple(t,s): + assert(valid_tuple(t,s)) + #B = [0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3] + oriented_face = faces_oriented[t[2]]*3 + edge = s[1][t[1]] + vertex = s[0][t[0]] + e1 = edge - vertex + B = oriented_face + A = [list(vertex)[0], list(e1)[0]] + return any(A == B[i:i + len(A)] for i in range(len(B)-len(A) + 1)) # check for sublist + +# len([t for t in all_tuples(s) if (valid_tuple(t,s) and ccw_tuple(t,s))]) + +# Enumerates all valid tuples similar to t, but with a different value in the slot d +# There must be 2 of them, and this function returns the one that is different than t +def switch(t,d,s): + return SimplexComplex(s).switch(t,d) + + + +# Builds a table for the switch operation of dimension d +def table(d,s): + # Generates a table for switch_vertex + sv = all_tuples(s) + + for i in range(len(sv)): + if not valid_tuple(sv[i],s): + sv[i] = len(s) * (-1,) + else: + sv[i] = switch(sv[i],d,s) + + return sv + + +# Builds a table for the switch operation of dimension d +def table_ccw(s): + # Generates a table for switch_vertex + sv = all_tuples(s) + out = [-1 for i in sv] + + for i in range(len(sv)): + if not valid_tuple(sv[i],s): + out[i] = -1 + else: + if ccw_tuple(sv[i],s): + out[i] = 1 + else: + out[i] = 0 + + return out + +# table_ccw("auto_3d_table_ccw",s) + +def table_complete_tuple(d,s): + # Generates a table for switch_vertex + sv = [t for t in all_tuples(s) if (valid_tuple(t,s) and ccw_tuple(t,s))] + out = [] + for c in range(len(s[d])): + for i in range(len(sv)): + if c == sv[i][d]: + out.append(sv[i]) + break + + assert(len(out) == len(s[d])) + + return out + + + + + diff --git a/scripts/templates/SimplexDart.hpp.template b/scripts/templates/SimplexDart.hpp.template new file mode 100644 index 0000000000..fdc2081110 --- /dev/null +++ b/scripts/templates/SimplexDart.hpp.template @@ -0,0 +1,39 @@ +#pragma once +// DO NOT MODIFY, autogenerated from the /scripts directory +#include +#include +#include +#include +#include "autogenerated_tables.hpp" + +namespace wmtk::autogen::{{ namespace }} { +class SimplexDart +{ +public: + SimplexDart(); + + static int8_t product(int8_t a, int8_t b) { return auto_valid_switch_product_table[b][a]; } + static int8_t inverse(int8_t a) { return auto_valid_switch_inverse_table[a]; } + static int8_t primitive_to_index(wmtk::PrimitiveType pt) + { + return auto_valid_tuple_switch_indices[get_primitive_type_id(pt)]; + } + static int8_t identity() { return primitive_to_index(wmtk::PrimitiveType::{{ type }} ); } + constexpr static size_t size() { return sizeof(auto_valid_tuple_indices) / sizeof(int8_t); } + + static auto valid_indices() { return wmtk::utils::array_to_map(auto_valid_tuple_indices); } + static auto valid_indices_dynamic() + { + return VectorX::ConstMapType(auto_valid_tuple_indices, size()); + } + + // constexpr static Eigen::Map> + // constexpr static auto valid_indices() + //{ + // return Vector namespace wmtk::autogen::{{ namespace }} { {% for table in tables %} {%- if "comment" in table -%} // {{ table.comment }} {%- endif %} - extern {% include "array_declaration.template" -%}; + extern {% include "templates/array_declaration.template" -%}; {% endfor %} } + diff --git a/scripts/templates/subgroup_transformations.cpp.template b/scripts/templates/subgroup_transformations.cpp.template new file mode 100644 index 0000000000..a3e51e64b3 --- /dev/null +++ b/scripts/templates/subgroup_transformations.cpp.template @@ -0,0 +1,30 @@ + +{% 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 "{{ filename }}.hpp" +// DO NOT MODIFY, autogenerated from the /scripts directory +namespace wmtk::autogen::{{ namespace }} { + {% for table in tables %} + {% include "templates/array_declaration.template" %} = {{ print_array(table.data) }}; + {% endfor %} + + const int8_t *remap_table[ {{ dimensions }} ][ {{ dimensions }}] = { + {% for row in range( dimensions ) %} + { + {% for col in range( dimensions ) %} + subgroup_indices_{{ row }}_{{ col}}, + {% endfor %} + }, + {% endfor %} + }; +} + diff --git a/scripts/templates/subgroup_transformations.hpp.template b/scripts/templates/subgroup_transformations.hpp.template new file mode 100644 index 0000000000..d86a520194 --- /dev/null +++ b/scripts/templates/subgroup_transformations.hpp.template @@ -0,0 +1,15 @@ +#pragma once + +// DO NOT MODIFY, autogenerated from the /scripts directory + +#include +namespace wmtk::autogen::{{ namespace }} { + {% for table in tables %} + {%- if "comment" in table -%} + // {{ table.comment }} + {%- endif %} + extern {% include "templates/array_declaration.template" -%}; + {% endfor %} + extern const int8_t *remap_table[ {{ dimensions }} ][ {{dimensions }}]; +} + diff --git a/scripts/templates/valid_index_from_tuple.hpp.template b/scripts/templates/valid_index_from_tuple.hpp.template new file mode 100644 index 0000000000..2d412c798d --- /dev/null +++ b/scripts/templates/valid_index_from_tuple.hpp.template @@ -0,0 +1,12 @@ + +#pragma once +// DO NOT MODIFY, autogenerated from the /scripts directory +#include + +namespace wmtk::autogen::{{ namespace }} { +int8_t valid_index_from_tuple(const Tuple& t); + +} + +#include "valid_index_from_tuple.hxx" +# diff --git a/scripts/templates/valid_index_from_tuple.hxx.template b/scripts/templates/valid_index_from_tuple.hxx.template new file mode 100644 index 0000000000..f030eca28d --- /dev/null +++ b/scripts/templates/valid_index_from_tuple.hxx.template @@ -0,0 +1,18 @@ + +#pragma once +// DO NOT MODIFY, autogenerated from the /scripts directory +#include "autogenerated_tables.hpp" +#include "local_id_table_offset.hpp" +#include "valid_index_from_tuple.hpp" +namespace wmtk::autogen::{{ namespace }} { +inline int8_t valid_index_from_tuple(const Tuple& t) +{ + { + const int64_t offset = local_id_table_offset(t); + const int8_t valid_index = auto_all_to_valid_tuple_indices[offset]; + return valid_index; + } + +} +} + diff --git a/src/wmtk/autogen/CMakeLists.txt b/src/wmtk/autogen/CMakeLists.txt index 436d87fc99..9c70aaa753 100644 --- a/src/wmtk/autogen/CMakeLists.txt +++ b/src/wmtk/autogen/CMakeLists.txt @@ -1,31 +1,46 @@ set(SRC_FILES - tet_mesh/autogenerated_tables.hpp - tet_mesh/autogenerated_tables.cpp - tet_mesh/local_switch_tuple.hpp - tet_mesh/local_switch_tuple.hxx - tet_mesh/is_ccw.hpp - tet_mesh/is_ccw.hxx - tet_mesh/local_id_table_offset.hxx - 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.hxx - tri_mesh/is_ccw.hpp - tri_mesh/is_ccw.hxx - tri_mesh/local_id_table_offset.hxx - tri_mesh/local_id_table_offset.hpp - - edge_mesh/local_switch_tuple.hpp - edge_mesh/local_switch_tuple.hxx - edge_mesh/is_ccw.hpp - edge_mesh/is_ccw.hxx is_ccw.hpp is_ccw.cpp local_switch_tuple.hpp local_switch_tuple.cpp + + SimplexDart.hpp + SimplexDart.cpp + + tuple_from_valid_index.hpp + tuple_from_valid_index.cpp + + valid_index_from_tuple.hpp + valid_index_from_tuple.cpp + + subgroup/subgroup_transformations.cpp + subgroup/subgroup_transformations.hpp + subgroup/convert.hxx + subgroup/convert.hpp + + point_mesh/SimplexDart.hpp + point_mesh/SimplexDart.cpp ) + +foreach(MESH_TYPE edge_mesh tri_mesh tet_mesh) + set(SRC_FILES ${SRC_FILES} + ${MESH_TYPE}/autogenerated_tables.hpp + ${MESH_TYPE}/autogenerated_tables.cpp + ${MESH_TYPE}/valid_index_from_tuple.hpp + ${MESH_TYPE}/valid_index_from_tuple.hxx + ${MESH_TYPE}/tuple_from_valid_index.hpp + ${MESH_TYPE}/tuple_from_valid_index.hxx + ${MESH_TYPE}/SimplexDart.hpp + ${MESH_TYPE}/local_switch_tuple.hpp + ${MESH_TYPE}/local_switch_tuple.hxx + ${MESH_TYPE}/is_ccw.hpp + ${MESH_TYPE}/is_ccw.hxx + ${MESH_TYPE}/local_id_table_offset.hxx + ${MESH_TYPE}/local_id_table_offset.hpp + ) + +endforeach() + target_sources(wildmeshing_toolkit PRIVATE ${SRC_FILES}) diff --git a/src/wmtk/autogen/SimplexDart.cpp b/src/wmtk/autogen/SimplexDart.cpp new file mode 100644 index 0000000000..f307ab0008 --- /dev/null +++ b/src/wmtk/autogen/SimplexDart.cpp @@ -0,0 +1,125 @@ +#include "SimplexDart.hpp" +#include +#include +#include "edge_mesh/SimplexDart.hpp" +#include "point_mesh/SimplexDart.hpp" +#include "subgroup/convert.hpp" +#include "tet_mesh/SimplexDart.hpp" +#include "tri_mesh/SimplexDart.hpp" +#include "tuple_from_valid_index.hpp" +#include "valid_index_from_tuple.hpp" + +namespace wmtk::autogen { +namespace { + + +/* +int8_t empty_binary(int8_t,int8_t){ + assert(false); +} + +int8_t empty_unary(int8_t){ + assert(false); +} +int8_t empty_unary(){ + assert(false); +} + +template + void f(); + +template SimplexDart::RETTYPE \ + { \ + switch (pt) { \ + case PrimitiveType::Edge: return &edge_mesh::SimplexDart::NAME; \ + case PrimitiveType::Triangle: return &tri_mesh::SimplexDart::NAME; \ + case PrimitiveType::Tetrahedron: return &tet_mesh::SimplexDart::NAME; \ + case PrimitiveType::Vertex: return &point_mesh::SimplexDart::NAME; \ + default: assert(false); \ + } \ + return nullptr; \ + } +GET_OP(product, binary_op_type) +GET_OP(inverse, unary_op_type) +GET_OP(primitive_to_index, primitive_to_index_type) +GET_OP(identity, nullary_op_type) +} // namespace + +#define FORWARD_OP(NAME, OP, RETTYPE, DEFAULT) \ + auto SimplexDart::NAME() const -> RETTYPE \ + { \ + switch (m_simplex_type) { \ + case PrimitiveType::Edge: return edge_mesh::SimplexDart::OP(); \ + case PrimitiveType::Triangle: return tri_mesh::SimplexDart::OP(); \ + case PrimitiveType::Tetrahedron: return tet_mesh::SimplexDart::OP(); \ + case PrimitiveType::Vertex: return point_mesh::SimplexDart::OP(); \ + default: assert(false); \ + } \ + return DEFAULT; \ + } + +FORWARD_OP(size, size, size_t, {}) +using DynamicIntMap = VectorX::ConstMapType; +namespace { +const static DynamicIntMap nullmap = DynamicIntMap(nullptr, 0); +} +FORWARD_OP(valid_indices, valid_indices_dynamic, DynamicIntMap, nullmap) + +SimplexDart::SimplexDart(wmtk::PrimitiveType simplex_type) + : m_simplex_type(simplex_type) + , m_product(get_product(simplex_type)) + , m_inverse(get_inverse(simplex_type)) + , m_primitive_to_index(get_primitive_to_index(simplex_type)) + , m_identity(get_identity(simplex_type)) +{} + +int8_t SimplexDart::product(int8_t a, int8_t b) const +{ + return m_product(a, b); +} +int8_t SimplexDart::inverse(int8_t a) const +{ + return m_inverse(a); +} +int8_t SimplexDart::primitive_as_index(wmtk::PrimitiveType pt) const +{ + return m_primitive_to_index(pt); +} +int8_t SimplexDart::identity() const +{ + return m_identity(); +} +wmtk::Tuple SimplexDart::tuple_from_valid_index(int64_t gid, int8_t index) const +{ + return wmtk::autogen::tuple_from_valid_index(m_simplex_type, gid, index); +} +wmtk::Tuple SimplexDart::update_tuple_from_valid_index(const Tuple& t, int8_t index) const +{ + return wmtk::autogen::tuple_from_valid_index( + m_simplex_type, + wmtk::utils::TupleInspector::global_cid(t), + index); +} +int8_t SimplexDart::valid_index_from_tuple(const wmtk::Tuple& t) const +{ + return wmtk::autogen::valid_index_from_tuple(m_simplex_type, t); +} + +int8_t SimplexDart::convert(int8_t valid_index, const SimplexDart& target) const +{ + if (target.m_simplex_type == PrimitiveType::Vertex) { + return 0; + } else if (m_simplex_type == PrimitiveType::Vertex) { + return target.identity(); + } else { + return subgroup::convert(m_simplex_type, target.m_simplex_type, valid_index); + } +} + + +} // namespace wmtk::autogen diff --git a/src/wmtk/autogen/SimplexDart.hpp b/src/wmtk/autogen/SimplexDart.hpp new file mode 100644 index 0000000000..909f93cf2d --- /dev/null +++ b/src/wmtk/autogen/SimplexDart.hpp @@ -0,0 +1,40 @@ +#pragma once +#include +#include +#include + +namespace wmtk::autogen { +class SimplexDart +{ +public: + SimplexDart(wmtk::PrimitiveType simplex_type); + + int8_t product(int8_t a, int8_t b) const; + int8_t inverse(int8_t a) const; + int8_t primitive_as_index(wmtk::PrimitiveType pt) const; + int8_t identity() const; + wmtk::Tuple tuple_from_valid_index(int64_t gid, int8_t valid_index) const; + wmtk::Tuple update_tuple_from_valid_index(const Tuple& t, int8_t valid_index) const; + + int8_t valid_index_from_tuple(const wmtk::Tuple& t) const; + + using binary_op_type = int8_t (*)(int8_t, int8_t); + using unary_op_type = int8_t (*)(int8_t); + using primitive_to_index_type = int8_t (*)(PrimitiveType); + using nullary_op_type = int8_t (*)(); + + size_t size() const; + VectorX::ConstMapType valid_indices() const; + + + // converts input valid_indx to the target mesh + int8_t convert(int8_t valid_index, const SimplexDart& target) const; + +private: + const wmtk::PrimitiveType m_simplex_type; + const binary_op_type m_product; + const unary_op_type m_inverse; + const primitive_to_index_type m_primitive_to_index; + const nullary_op_type m_identity; +}; +} // namespace wmtk::autogen diff --git a/src/wmtk/autogen/edge_mesh/SimplexDart.hpp b/src/wmtk/autogen/edge_mesh/SimplexDart.hpp new file mode 100644 index 0000000000..a2209837dc --- /dev/null +++ b/src/wmtk/autogen/edge_mesh/SimplexDart.hpp @@ -0,0 +1,38 @@ +#pragma once +// DO NOT MODIFY, autogenerated from the /scripts directory +#include +#include +#include +#include +#include "autogenerated_tables.hpp" + +namespace wmtk::autogen::edge_mesh { +class SimplexDart +{ +public: + SimplexDart(); + + static int8_t product(int8_t a, int8_t b) { return auto_valid_switch_product_table[b][a]; } + static int8_t inverse(int8_t a) { return auto_valid_switch_inverse_table[a]; } + static int8_t primitive_to_index(wmtk::PrimitiveType pt) + { + return auto_valid_tuple_switch_indices[get_primitive_type_id(pt)]; + } + static int8_t identity() { return primitive_to_index(wmtk::PrimitiveType::Edge); } + constexpr static size_t size() { return sizeof(auto_valid_tuple_indices) / sizeof(int8_t); } + + static auto valid_indices() { return wmtk::utils::array_to_map(auto_valid_tuple_indices); } + static auto valid_indices_dynamic() + { + return VectorX::ConstMapType(auto_valid_tuple_indices, size()); + } + + // constexpr static Eigen::Map> + // constexpr static auto valid_indices() + //{ + // return Vector +namespace wmtk::autogen::edge_mesh { +// Valid tuple local indices +extern const int8_t auto_valid_tuples[2][1]; + +// For each valid tuple encodes the raw tuple index +extern const int8_t auto_valid_tuple_indices[2]; + +// Index of each tuple according to valid tuple indexing +extern const int8_t auto_all_to_valid_tuple_indices[2]; + +// Valid tuple indices +extern const int8_t auto_valid_switch_table[2][1]; + +// Tuple group product using valid tuple indices +extern const int8_t auto_valid_switch_product_table[2][2]; + +// Tuple group product inverse using valid tuple indices +extern const int8_t auto_valid_switch_inverse_table[2]; + +// Which tuples are associated with switching. Last entry is the identity tuple +extern const int8_t auto_valid_tuple_switch_indices[2]; + + +} // namespace wmtk::autogen::edge_mesh diff --git a/src/wmtk/autogen/edge_mesh/is_ccw.hxx b/src/wmtk/autogen/edge_mesh/is_ccw.hxx index 390fc28da7..0c2a3f4fe6 100644 --- a/src/wmtk/autogen/edge_mesh/is_ccw.hxx +++ b/src/wmtk/autogen/edge_mesh/is_ccw.hxx @@ -13,6 +13,9 @@ inline bool is_ccw(const Tuple& tuple) } inline bool tuple_is_valid_for_ccw(const Tuple& tuple) { + if (tuple.is_null()) { + return false; + } return true; } } // namespace wmtk::autogen::edge_mesh diff --git a/src/wmtk/autogen/edge_mesh/local_id_table_offset.hpp b/src/wmtk/autogen/edge_mesh/local_id_table_offset.hpp new file mode 100644 index 0000000000..91bbe00ac1 --- /dev/null +++ b/src/wmtk/autogen/edge_mesh/local_id_table_offset.hpp @@ -0,0 +1,15 @@ +#pragma once +#include +#include + + +namespace wmtk::autogen::edge_mesh { +// computes the offset of a tuple's local ids in the tables +int64_t local_id_table_offset(const Tuple& t); + +// returns a lvid/leid associated iwth a particular tuple offset +std::array lvid_from_table_offset(int64_t table_offset); + +} // namespace wmtk::autogen::edge_mesh + +#include "local_id_table_offset.hxx" diff --git a/src/wmtk/autogen/edge_mesh/local_id_table_offset.hxx b/src/wmtk/autogen/edge_mesh/local_id_table_offset.hxx new file mode 100644 index 0000000000..37a4cc7fdd --- /dev/null +++ b/src/wmtk/autogen/edge_mesh/local_id_table_offset.hxx @@ -0,0 +1,22 @@ +#pragma once + +#include +#include "autogenerated_tables.hpp" +namespace wmtk::autogen::edge_mesh { +// computes the offset of a tuple's local ids in the tables +inline int64_t local_id_table_offset(const Tuple& tuple) +{ + using namespace utils; + return TupleInspector::local_vid(tuple); +} + +inline std::array lvid_from_table_offset(int64_t table_offset) +{ + std::array r; + auto& [lvid] = r; + + lvid = table_offset; + return r; +} + +} // namespace wmtk::autogen::edge_mesh diff --git a/src/wmtk/autogen/edge_mesh/local_switch_tuple.hpp b/src/wmtk/autogen/edge_mesh/local_switch_tuple.hpp index 9c9ee0a90a..53b6addbb3 100644 --- a/src/wmtk/autogen/edge_mesh/local_switch_tuple.hpp +++ b/src/wmtk/autogen/edge_mesh/local_switch_tuple.hpp @@ -4,6 +4,12 @@ namespace wmtk::autogen::edge_mesh { Tuple local_switch_tuple(const Tuple& t, PrimitiveType pt); +Tuple local_switch_tuple(const Tuple& t, int8_t index); + +namespace internal { + int8_t switch_primitive_to_valid_tuple_index(wmtk::PrimitiveType pt); + int8_t identity_valid_tuple_index(); +} } #include "local_switch_tuple.hxx" diff --git a/src/wmtk/autogen/edge_mesh/local_switch_tuple.hxx b/src/wmtk/autogen/edge_mesh/local_switch_tuple.hxx index ce419b5705..95459e44ec 100644 --- a/src/wmtk/autogen/edge_mesh/local_switch_tuple.hxx +++ b/src/wmtk/autogen/edge_mesh/local_switch_tuple.hxx @@ -2,6 +2,10 @@ #include #include #include +#include "autogenerated_tables.hpp" +#include "local_id_table_offset.hpp" +#include "tuple_from_valid_index.hpp" +#include "valid_index_from_tuple.hpp" namespace wmtk::autogen::edge_mesh { inline Tuple local_switch_tuple(const Tuple& tuple, PrimitiveType pt) @@ -25,4 +29,24 @@ inline Tuple local_switch_tuple(const Tuple& tuple, PrimitiveType pt) } return Tuple(); } + +inline Tuple local_switch_tuple(const Tuple& t, int8_t valid_tuple_index) +{ + int8_t input_index = valid_index_from_tuple(t); + const int64_t global_cid = wmtk::utils::TupleInspector::global_cid(t); + const int64_t hash = wmtk::utils::TupleInspector::hash(t); + const int8_t product_result = auto_valid_switch_product_table[input_index][valid_tuple_index]; + return tuple_from_valid_index(global_cid, product_result, hash); +} + +namespace internal { +inline int8_t switch_primitive_to_valid_tuple_index(wmtk::PrimitiveType pt) +{ + return auto_valid_tuple_switch_indices[get_primitive_type_id(pt)]; +} +inline int8_t identity_valid_tuple_index() +{ + return switch_primitive_to_valid_tuple_index(wmtk::PrimitiveType::Edge); +} +} // namespace internal } // namespace wmtk::autogen::edge_mesh diff --git a/src/wmtk/autogen/edge_mesh/tuple_from_valid_index.hpp b/src/wmtk/autogen/edge_mesh/tuple_from_valid_index.hpp new file mode 100644 index 0000000000..86e39b668d --- /dev/null +++ b/src/wmtk/autogen/edge_mesh/tuple_from_valid_index.hpp @@ -0,0 +1,10 @@ +// DO NOT MODIFY, autogenerated from the /scripts directory +#pragma once +namespace wmtk::autogen::edge_mesh { + +Tuple tuple_from_valid_index(int64_t global_cid, int8_t valid_tuple_index); +Tuple tuple_from_valid_index(int64_t global_cid, int8_t valid_tuple_index, int64_t hash); + +} // namespace wmtk::autogen::edge_mesh + +#include "tuple_from_valid_index.hxx" diff --git a/src/wmtk/autogen/edge_mesh/tuple_from_valid_index.hxx b/src/wmtk/autogen/edge_mesh/tuple_from_valid_index.hxx new file mode 100644 index 0000000000..8d5f2ccfc0 --- /dev/null +++ b/src/wmtk/autogen/edge_mesh/tuple_from_valid_index.hxx @@ -0,0 +1,20 @@ +#pragma once +// DO NOT MODIFY, autogenerated from the /scripts directory +#include "autogenerated_tables.hpp" +#include "tuple_from_valid_index.hpp" + +namespace wmtk::autogen::edge_mesh { +inline Tuple tuple_from_valid_index(int64_t global_cid, int8_t valid_tuple_index) +{ + const auto& [lvid] = auto_valid_tuples[valid_tuple_index]; + + return Tuple(lvid, -1, -1, global_cid); +} +inline Tuple tuple_from_valid_index(int64_t global_cid, int8_t valid_tuple_index, int64_t hash) +{ + const auto& [lvid] = auto_valid_tuples[valid_tuple_index]; + + return Tuple(lvid, -1, -1, global_cid, hash); +} + +} // namespace wmtk::autogen::edge_mesh diff --git a/src/wmtk/autogen/edge_mesh/valid_index_from_tuple.hpp b/src/wmtk/autogen/edge_mesh/valid_index_from_tuple.hpp new file mode 100644 index 0000000000..9e3f25977a --- /dev/null +++ b/src/wmtk/autogen/edge_mesh/valid_index_from_tuple.hpp @@ -0,0 +1,12 @@ + +#pragma once +// DO NOT MODIFY, autogenerated from the /scripts directory +#include + +namespace wmtk::autogen::edge_mesh { +int8_t valid_index_from_tuple(const Tuple& t); + +} + +#include "valid_index_from_tuple.hxx" +# \ No newline at end of file diff --git a/src/wmtk/autogen/edge_mesh/valid_index_from_tuple.hxx b/src/wmtk/autogen/edge_mesh/valid_index_from_tuple.hxx new file mode 100644 index 0000000000..bf8e0182b2 --- /dev/null +++ b/src/wmtk/autogen/edge_mesh/valid_index_from_tuple.hxx @@ -0,0 +1,16 @@ + +#pragma once +// DO NOT MODIFY, autogenerated from the /scripts directory +#include "autogenerated_tables.hpp" +#include "local_id_table_offset.hpp" +#include "valid_index_from_tuple.hpp" +namespace wmtk::autogen::edge_mesh { +inline int8_t valid_index_from_tuple(const Tuple& t) +{ + { + const int64_t offset = local_id_table_offset(t); + const int8_t valid_index = auto_all_to_valid_tuple_indices[offset]; + return valid_index; + } +} +} // namespace wmtk::autogen::edge_mesh diff --git a/src/wmtk/autogen/local_switch_tuple.cpp b/src/wmtk/autogen/local_switch_tuple.cpp index f070fc3f89..8e9269ad1a 100644 --- a/src/wmtk/autogen/local_switch_tuple.cpp +++ b/src/wmtk/autogen/local_switch_tuple.cpp @@ -12,6 +12,44 @@ Tuple local_switch_tuple(PrimitiveType mesh_type, const Tuple& t, PrimitiveType case PrimitiveType::Vertex: default: assert(false); // "not implemented" } - return Tuple(); + return {}; } +Tuple local_switch_tuple(PrimitiveType mesh_type, const Tuple& t, int8_t valid_tuple_index) +{ + switch (mesh_type) { + case PrimitiveType::Triangle: return tri_mesh::local_switch_tuple(t, valid_tuple_index); + case PrimitiveType::Tetrahedron: return tet_mesh::local_switch_tuple(t, valid_tuple_index); + case PrimitiveType::Edge: return edge_mesh::local_switch_tuple(t, valid_tuple_index); + case PrimitiveType::Vertex: + default: assert(false); // "not implemented" + } + return {}; +} + +namespace internal { +int8_t switch_primitive_to_valid_tuple_index(PrimitiveType mesh_type, PrimitiveType pt) +{ + switch (mesh_type) { + case PrimitiveType::Tetrahedron: + return tet_mesh::internal::switch_primitive_to_valid_tuple_index(pt); + case PrimitiveType::Triangle: + return tri_mesh::internal::switch_primitive_to_valid_tuple_index(pt); + case PrimitiveType::Edge: return edge_mesh::internal::switch_primitive_to_valid_tuple_index(pt); + case PrimitiveType::Vertex: + default: assert(false); // "not implemented" + } + return {}; +} +int8_t identity_valid_tuple_index(PrimitiveType mesh_type) +{ + switch (mesh_type) { + case PrimitiveType::Tetrahedron: return tet_mesh::internal::identity_valid_tuple_index(); + case PrimitiveType::Triangle: return tri_mesh::internal::identity_valid_tuple_index(); + case PrimitiveType::Edge: return edge_mesh::internal::identity_valid_tuple_index(); + case PrimitiveType::Vertex: + default: assert(false); // "not implemented" + } + return {}; +} +} // namespace internal } // namespace wmtk::autogen diff --git a/src/wmtk/autogen/local_switch_tuple.hpp b/src/wmtk/autogen/local_switch_tuple.hpp index 87c2472783..a0f60f0611 100644 --- a/src/wmtk/autogen/local_switch_tuple.hpp +++ b/src/wmtk/autogen/local_switch_tuple.hpp @@ -6,4 +6,10 @@ // NOTE: this header primarily exists to simplify unit testing, not really for use namespace wmtk::autogen { Tuple local_switch_tuple(PrimitiveType mesh_type, const Tuple& t, PrimitiveType pt); -} +Tuple local_switch_tuple(PrimitiveType mesh_type, const Tuple& t, int8_t valid_tuple_index); + +namespace internal { +int8_t switch_primitive_to_valid_tuple_index(PrimitiveType mesh_type, PrimitiveType pt); +int8_t identity_valid_tuple_index(PrimitiveType mesh_type); +} // namespace internal +} // namespace wmtk::autogen diff --git a/src/wmtk/autogen/point_mesh/SimplexDart.cpp b/src/wmtk/autogen/point_mesh/SimplexDart.cpp new file mode 100644 index 0000000000..8ea41f2909 --- /dev/null +++ b/src/wmtk/autogen/point_mesh/SimplexDart.cpp @@ -0,0 +1,4 @@ +#include "SimplexDart.hpp" +namespace wmtk::autogen::point_mesh { +const std::array SimplexDart::_indices = {{0}}; +} diff --git a/src/wmtk/autogen/point_mesh/SimplexDart.hpp b/src/wmtk/autogen/point_mesh/SimplexDart.hpp new file mode 100644 index 0000000000..6d522183d4 --- /dev/null +++ b/src/wmtk/autogen/point_mesh/SimplexDart.hpp @@ -0,0 +1,38 @@ + +#pragma once +// DO NOT MODIFY, autogenerated from the /scripts directory +#include +#include +#include +#include +#include + +namespace wmtk::autogen::point_mesh { +class SimplexDart +{ +public: + SimplexDart(); + + static int8_t product(int8_t a, int8_t b) + { + assert(a == 0 && b == 0); + return 0; + } + static int8_t inverse(int8_t a) { return 0; } + static int8_t primitive_to_index(wmtk::PrimitiveType) { return 0; } + static int8_t identity() { return 0; } + constexpr static size_t size() { return 1; } + + const static std::array _indices; + static auto valid_indices() { return Vector::ConstMapType(_indices.data()); } + static auto valid_indices_dynamic() { return VectorX::ConstMapType(_indices.data(), size()); } + + // constexpr static Eigen::Map> + // constexpr static auto valid_indices() + //{ + // return Vector + +namespace wmtk::autogen::subgroup { + + int8_t convert(PrimitiveType from, PrimitiveType to, int8_t source); + int8_t convert(int8_t from, int8_t to, int8_t source); + +} + +#include "convert.hxx" diff --git a/src/wmtk/autogen/subgroup/convert.hxx b/src/wmtk/autogen/subgroup/convert.hxx new file mode 100644 index 0000000000..67a836344f --- /dev/null +++ b/src/wmtk/autogen/subgroup/convert.hxx @@ -0,0 +1,13 @@ +#pragma once + +#include "convert.hpp" +#include "subgroup_transformations.hpp" +namespace wmtk::autogen::subgroup { + + inline int8_t convert(PrimitiveType from, PrimitiveType to, int8_t source) { + return convert(int8_t(from), int8_t(to), source); + } + inline int8_t convert(int8_t from, int8_t to, int8_t source) { + return remap_table[from-1][to-1][source]; + } +} diff --git a/src/wmtk/autogen/subgroup/subgroup_transformations.cpp b/src/wmtk/autogen/subgroup/subgroup_transformations.cpp new file mode 100644 index 0000000000..51ae7a022c --- /dev/null +++ b/src/wmtk/autogen/subgroup/subgroup_transformations.cpp @@ -0,0 +1,62 @@ + + +#include "subgroup_transformations.hpp" +// DO NOT MODIFY, autogenerated from the /scripts directory +namespace wmtk::autogen::subgroup { + +const int8_t subgroup_indices_0_0[2] = {0, 1}; + +const int8_t subgroup_indices_1_0[6] = {-1, 0, -1, 1, -1, -1}; + +const int8_t subgroup_indices_0_1[2] = {1, 3}; + +const int8_t subgroup_indices_1_1[6] = {0, 1, 2, 3, 4, 5}; + +const int8_t subgroup_indices_2_0[24] = {-1, 0, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + +const int8_t subgroup_indices_0_2[2] = {1, 7}; + +const int8_t subgroup_indices_2_1[24] = {-1, 1, -1, 0, -1, -1, -1, 3, -1, 2, -1, -1, + -1, 5, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1}; + +const int8_t subgroup_indices_1_2[6] = {3, 1, 9, 7, 15, 13}; + +const int8_t subgroup_indices_2_2[24] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}; + + +const int8_t* remap_table[3][3] = { + + { + + subgroup_indices_0_0, + + subgroup_indices_0_1, + + subgroup_indices_0_2, + + }, + + { + + subgroup_indices_1_0, + + subgroup_indices_1_1, + + subgroup_indices_1_2, + + }, + + { + + subgroup_indices_2_0, + + subgroup_indices_2_1, + + subgroup_indices_2_2, + + }, + +}; +} // namespace wmtk::autogen::subgroup diff --git a/src/wmtk/autogen/subgroup/subgroup_transformations.hpp b/src/wmtk/autogen/subgroup/subgroup_transformations.hpp new file mode 100644 index 0000000000..31087c1a07 --- /dev/null +++ b/src/wmtk/autogen/subgroup/subgroup_transformations.hpp @@ -0,0 +1,27 @@ +#pragma once + +// DO NOT MODIFY, autogenerated from the /scripts directory + +#include +namespace wmtk::autogen::subgroup { + +extern const int8_t subgroup_indices_0_0[2]; + +extern const int8_t subgroup_indices_1_0[6]; + +extern const int8_t subgroup_indices_0_1[2]; + +extern const int8_t subgroup_indices_1_1[6]; + +extern const int8_t subgroup_indices_2_0[24]; + +extern const int8_t subgroup_indices_0_2[2]; + +extern const int8_t subgroup_indices_2_1[24]; + +extern const int8_t subgroup_indices_1_2[6]; + +extern const int8_t subgroup_indices_2_2[24]; + +extern const int8_t* remap_table[3][3]; +} // namespace wmtk::autogen::subgroup diff --git a/src/wmtk/autogen/tet_mesh/SimplexDart.hpp b/src/wmtk/autogen/tet_mesh/SimplexDart.hpp new file mode 100644 index 0000000000..f976e85892 --- /dev/null +++ b/src/wmtk/autogen/tet_mesh/SimplexDart.hpp @@ -0,0 +1,38 @@ +#pragma once +// DO NOT MODIFY, autogenerated from the /scripts directory +#include +#include +#include +#include +#include "autogenerated_tables.hpp" + +namespace wmtk::autogen::tet_mesh { +class SimplexDart +{ +public: + SimplexDart(); + + static int8_t product(int8_t a, int8_t b) { return auto_valid_switch_product_table[b][a]; } + static int8_t inverse(int8_t a) { return auto_valid_switch_inverse_table[a]; } + static int8_t primitive_to_index(wmtk::PrimitiveType pt) + { + return auto_valid_tuple_switch_indices[get_primitive_type_id(pt)]; + } + static int8_t identity() { return primitive_to_index(wmtk::PrimitiveType::Tetrahedron); } + constexpr static size_t size() { return sizeof(auto_valid_tuple_indices) / sizeof(int8_t); } + + static auto valid_indices() { return wmtk::utils::array_to_map(auto_valid_tuple_indices); } + static auto valid_indices_dynamic() + { + return VectorX::ConstMapType(auto_valid_tuple_indices, size()); + } + + // constexpr static Eigen::Map> + // constexpr static auto valid_indices() + //{ + // return Vector - // DO NOT MODIFY, autogenerated from the /scripts directory +#include namespace wmtk::autogen::tet_mesh { // lvids for a specfic leid extern const int64_t auto_3d_edges[6][2]; @@ -32,5 +31,26 @@ extern const int64_t auto_3d_table_complete_edge[6][3]; // fvid -> a ccw [lvid,leid,lfid] extern const int64_t auto_3d_table_complete_face[4][3]; +// Valid tuple local indices +extern const int8_t auto_valid_tuples[24][3]; + +// For each valid tuple encodes the raw tuple index +extern const int8_t auto_valid_tuple_indices[24]; + +// Index of each tuple according to valid tuple indexing +extern const int8_t auto_all_to_valid_tuple_indices[96]; + +// Valid tuple indices +extern const int8_t auto_valid_switch_table[24][3]; + +// Tuple group product using valid tuple indices +extern const int8_t auto_valid_switch_product_table[24][24]; + +// Tuple group product inverse using valid tuple indices +extern const int8_t auto_valid_switch_inverse_table[24]; + +// Which tuples are associated with switching. Last entry is the identity tuple +extern const int8_t auto_valid_tuple_switch_indices[4]; + -} // namespace wmtk::autogen::tet_mesh \ No newline at end of file +} // 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 index 149a42a7e6..621a06fff4 100644 --- a/src/wmtk/autogen/tet_mesh/local_switch_tuple.hpp +++ b/src/wmtk/autogen/tet_mesh/local_switch_tuple.hpp @@ -4,6 +4,13 @@ namespace wmtk::autogen::tet_mesh { Tuple local_switch_tuple(const Tuple& t, PrimitiveType pt); + +Tuple local_switch_tuple(const Tuple& t, int8_t valid_tuple_index); +} + +namespace internal { + int8_t switch_primitive_to_valid_tuple_index(wmtk::PrimitiveType pt); + int8_t identity_valid_tuple_index(); } -#include "local_switch_tuple.hxx" \ No newline at end of file +#include "local_switch_tuple.hxx" diff --git a/src/wmtk/autogen/tet_mesh/local_switch_tuple.hxx b/src/wmtk/autogen/tet_mesh/local_switch_tuple.hxx index e4c74f0fc3..932923dcd2 100644 --- a/src/wmtk/autogen/tet_mesh/local_switch_tuple.hxx +++ b/src/wmtk/autogen/tet_mesh/local_switch_tuple.hxx @@ -4,6 +4,8 @@ #include #include "autogenerated_tables.hpp" #include "local_id_table_offset.hpp" +#include "tuple_from_valid_index.hpp" +#include "valid_index_from_tuple.hpp" namespace wmtk::autogen::tet_mesh { @@ -44,4 +46,24 @@ inline Tuple local_switch_tuple(const Tuple& tuple, PrimitiveType pt) } return Tuple(); } + +inline Tuple local_switch_tuple(const Tuple& t, int8_t valid_tuple_index) +{ + int8_t input_index = valid_index_from_tuple(t); + const int64_t global_cid = wmtk::utils::TupleInspector::global_cid(t); + const int64_t hash = wmtk::utils::TupleInspector::hash(t); + const int8_t product_result = auto_valid_switch_product_table[input_index][valid_tuple_index]; + return tuple_from_valid_index(global_cid, product_result, hash); +} + +namespace internal { +inline int8_t switch_primitive_to_valid_tuple_index(wmtk::PrimitiveType pt) +{ + return auto_valid_tuple_switch_indices[get_primitive_type_id(pt)]; +} +inline int8_t identity_valid_tuple_index() +{ + return switch_primitive_to_valid_tuple_index(wmtk::PrimitiveType::Tetrahedron); +} +} // namespace internal } // namespace wmtk::autogen::tet_mesh diff --git a/src/wmtk/autogen/tet_mesh/tuple_from_valid_index.hpp b/src/wmtk/autogen/tet_mesh/tuple_from_valid_index.hpp new file mode 100644 index 0000000000..2c9ffffa3d --- /dev/null +++ b/src/wmtk/autogen/tet_mesh/tuple_from_valid_index.hpp @@ -0,0 +1,10 @@ +// DO NOT MODIFY, autogenerated from the /scripts directory +#pragma once +namespace wmtk::autogen::tet_mesh { + +Tuple tuple_from_valid_index(int64_t global_cid, int8_t valid_tuple_index); +Tuple tuple_from_valid_index(int64_t global_cid, int8_t valid_tuple_index, int64_t hash); + +} // namespace wmtk::autogen::tet_mesh + +#include "tuple_from_valid_index.hxx" diff --git a/src/wmtk/autogen/tet_mesh/tuple_from_valid_index.hxx b/src/wmtk/autogen/tet_mesh/tuple_from_valid_index.hxx new file mode 100644 index 0000000000..0dee9a84c7 --- /dev/null +++ b/src/wmtk/autogen/tet_mesh/tuple_from_valid_index.hxx @@ -0,0 +1,20 @@ +#pragma once +// DO NOT MODIFY, autogenerated from the /scripts directory +#include "autogenerated_tables.hpp" +#include "tuple_from_valid_index.hpp" + +namespace wmtk::autogen::tet_mesh { +inline Tuple tuple_from_valid_index(int64_t global_cid, int8_t valid_tuple_index) +{ + const auto& [lvid, leid, lfid] = auto_valid_tuples[valid_tuple_index]; + + return Tuple(lvid, leid, lfid, global_cid); +} +inline Tuple tuple_from_valid_index(int64_t global_cid, int8_t valid_tuple_index, int64_t hash) +{ + const auto& [lvid, leid, lfid] = auto_valid_tuples[valid_tuple_index]; + + return Tuple(lvid, leid, lfid, global_cid, hash); +} + +} // namespace wmtk::autogen::tet_mesh diff --git a/src/wmtk/autogen/tet_mesh/valid_index_from_tuple.hpp b/src/wmtk/autogen/tet_mesh/valid_index_from_tuple.hpp new file mode 100644 index 0000000000..6610693b19 --- /dev/null +++ b/src/wmtk/autogen/tet_mesh/valid_index_from_tuple.hpp @@ -0,0 +1,12 @@ + +#pragma once +// DO NOT MODIFY, autogenerated from the /scripts directory +#include + +namespace wmtk::autogen::tet_mesh { +int8_t valid_index_from_tuple(const Tuple& t); + +} + +#include "valid_index_from_tuple.hxx" +# \ No newline at end of file diff --git a/src/wmtk/autogen/tet_mesh/valid_index_from_tuple.hxx b/src/wmtk/autogen/tet_mesh/valid_index_from_tuple.hxx new file mode 100644 index 0000000000..d57ea8a4e5 --- /dev/null +++ b/src/wmtk/autogen/tet_mesh/valid_index_from_tuple.hxx @@ -0,0 +1,16 @@ + +#pragma once +// DO NOT MODIFY, autogenerated from the /scripts directory +#include "autogenerated_tables.hpp" +#include "local_id_table_offset.hpp" +#include "valid_index_from_tuple.hpp" +namespace wmtk::autogen::tet_mesh { +inline int8_t valid_index_from_tuple(const Tuple& t) +{ + { + const int64_t offset = local_id_table_offset(t); + const int8_t valid_index = auto_all_to_valid_tuple_indices[offset]; + return valid_index; + } +} +} // namespace wmtk::autogen::tet_mesh diff --git a/src/wmtk/autogen/tri_mesh/SimplexDart.hpp b/src/wmtk/autogen/tri_mesh/SimplexDart.hpp new file mode 100644 index 0000000000..ddbeb144c1 --- /dev/null +++ b/src/wmtk/autogen/tri_mesh/SimplexDart.hpp @@ -0,0 +1,38 @@ +#pragma once +// DO NOT MODIFY, autogenerated from the /scripts directory +#include +#include +#include +#include +#include "autogenerated_tables.hpp" + +namespace wmtk::autogen::tri_mesh { +class SimplexDart +{ +public: + SimplexDart(); + + static int8_t product(int8_t a, int8_t b) { return auto_valid_switch_product_table[b][a]; } + static int8_t inverse(int8_t a) { return auto_valid_switch_inverse_table[a]; } + static int8_t primitive_to_index(wmtk::PrimitiveType pt) + { + return auto_valid_tuple_switch_indices[get_primitive_type_id(pt)]; + } + static int8_t identity() { return primitive_to_index(wmtk::PrimitiveType::Triangle); } + constexpr static size_t size() { return sizeof(auto_valid_tuple_indices) / sizeof(int8_t); } + + static auto valid_indices() { return wmtk::utils::array_to_map(auto_valid_tuple_indices); } + static auto valid_indices_dynamic() + { + return VectorX::ConstMapType(auto_valid_tuple_indices, size()); + } + + // constexpr static Eigen::Map> + // constexpr static auto valid_indices() + //{ + // return Vector - - // DO NOT MODIFY, autogenerated from the /scripts directory +#include namespace wmtk::autogen::tri_mesh { // lvids for a particular leid extern const int64_t auto_2d_edges[3][2]; @@ -24,5 +22,26 @@ extern const int64_t auto_2d_table_complete_vertex[3][2]; // leid -> a ccw [lvid,leid] extern const int64_t auto_2d_table_complete_edge[3][2]; +// Valid tuple local indices +extern const int8_t auto_valid_tuples[6][2]; + +// For each valid tuple encodes the raw tuple index +extern const int8_t auto_valid_tuple_indices[6]; + +// Index of each tuple according to valid tuple indexing +extern const int8_t auto_all_to_valid_tuple_indices[9]; + +// Valid tuple indices +extern const int8_t auto_valid_switch_table[6][2]; + +// Tuple group product using valid tuple indices +extern const int8_t auto_valid_switch_product_table[6][6]; + +// Tuple group product inverse using valid tuple indices +extern const int8_t auto_valid_switch_inverse_table[6]; + +// Which tuples are associated with switching. Last entry is the identity tuple +extern const int8_t auto_valid_tuple_switch_indices[3]; + -} // namespace wmtk::autogen::tri_mesh \ No newline at end of file +} // namespace wmtk::autogen::tri_mesh diff --git a/src/wmtk/autogen/tri_mesh/is_ccw.hxx b/src/wmtk/autogen/tri_mesh/is_ccw.hxx index e7f137458e..364c2a2574 100644 --- a/src/wmtk/autogen/tri_mesh/is_ccw.hxx +++ b/src/wmtk/autogen/tri_mesh/is_ccw.hxx @@ -17,6 +17,9 @@ inline bool is_ccw(const Tuple& tuple) inline bool tuple_is_valid_for_ccw(const Tuple& tuple) { using namespace utils; + if (tuple.is_null()) { + return false; + } const int64_t offset = local_id_table_offset(tuple); return auto_2d_table_ccw[offset] != -1; } diff --git a/src/wmtk/autogen/tri_mesh/local_switch_tuple.hpp b/src/wmtk/autogen/tri_mesh/local_switch_tuple.hpp index be2c3cf30e..d3f8f003e0 100644 --- a/src/wmtk/autogen/tri_mesh/local_switch_tuple.hpp +++ b/src/wmtk/autogen/tri_mesh/local_switch_tuple.hpp @@ -4,6 +4,12 @@ namespace wmtk::autogen::tri_mesh { Tuple local_switch_tuple(const Tuple& t, PrimitiveType pt); -} +Tuple local_switch_tuple(const Tuple& t, int8_t index); + +namespace internal { +int8_t switch_primitive_to_valid_tuple_index(wmtk::PrimitiveType pt); +int8_t identity_valid_tuple_index(); +} // namespace internal +} // namespace wmtk::autogen::tri_mesh #include "local_switch_tuple.hxx" diff --git a/src/wmtk/autogen/tri_mesh/local_switch_tuple.hxx b/src/wmtk/autogen/tri_mesh/local_switch_tuple.hxx index e70a8a505a..43be52413a 100644 --- a/src/wmtk/autogen/tri_mesh/local_switch_tuple.hxx +++ b/src/wmtk/autogen/tri_mesh/local_switch_tuple.hxx @@ -4,6 +4,8 @@ #include #include "autogenerated_tables.hpp" #include "local_id_table_offset.hpp" +#include "tuple_from_valid_index.hpp" +#include "valid_index_from_tuple.hpp" namespace wmtk::autogen::tri_mesh { @@ -34,4 +36,23 @@ inline Tuple local_switch_tuple(const Tuple& tuple, PrimitiveType pt) } return Tuple(); } +inline Tuple local_switch_tuple(const Tuple& t, int8_t valid_tuple_index) +{ + int8_t input_index = valid_index_from_tuple(t); + const int64_t global_cid = wmtk::utils::TupleInspector::global_cid(t); + const int64_t hash = wmtk::utils::TupleInspector::hash(t); + const int8_t product_result = auto_valid_switch_product_table[input_index][valid_tuple_index]; + return tuple_from_valid_index(global_cid, product_result, hash); +} + +namespace internal { +inline int8_t switch_primitive_to_valid_tuple_index(wmtk::PrimitiveType pt) +{ + return auto_valid_tuple_switch_indices[get_primitive_type_id(pt)]; +} +inline int8_t identity_valid_tuple_index() +{ + return switch_primitive_to_valid_tuple_index(wmtk::PrimitiveType::Triangle); +} +} // namespace internal } // namespace wmtk::autogen::tri_mesh diff --git a/src/wmtk/autogen/tri_mesh/tuple_from_valid_index.hpp b/src/wmtk/autogen/tri_mesh/tuple_from_valid_index.hpp new file mode 100644 index 0000000000..6a3e146937 --- /dev/null +++ b/src/wmtk/autogen/tri_mesh/tuple_from_valid_index.hpp @@ -0,0 +1,10 @@ +// DO NOT MODIFY, autogenerated from the /scripts directory +#pragma once +namespace wmtk::autogen::tri_mesh { + +Tuple tuple_from_valid_index(int64_t global_cid, int8_t valid_tuple_index); +Tuple tuple_from_valid_index(int64_t global_cid, int8_t valid_tuple_index, int64_t hash); + +} // namespace wmtk::autogen::tri_mesh + +#include "tuple_from_valid_index.hxx" diff --git a/src/wmtk/autogen/tri_mesh/tuple_from_valid_index.hxx b/src/wmtk/autogen/tri_mesh/tuple_from_valid_index.hxx new file mode 100644 index 0000000000..832e580e8b --- /dev/null +++ b/src/wmtk/autogen/tri_mesh/tuple_from_valid_index.hxx @@ -0,0 +1,20 @@ +#pragma once +// DO NOT MODIFY, autogenerated from the /scripts directory +#include "autogenerated_tables.hpp" +#include "tuple_from_valid_index.hpp" + +namespace wmtk::autogen::tri_mesh { +inline Tuple tuple_from_valid_index(int64_t global_cid, int8_t valid_tuple_index) +{ + const auto& [lvid, leid] = auto_valid_tuples[valid_tuple_index]; + + return Tuple(lvid, leid, -1, global_cid); +} +inline Tuple tuple_from_valid_index(int64_t global_cid, int8_t valid_tuple_index, int64_t hash) +{ + const auto& [lvid, leid] = auto_valid_tuples[valid_tuple_index]; + + return Tuple(lvid, leid, -1, global_cid, hash); +} + +} // namespace wmtk::autogen::tri_mesh diff --git a/src/wmtk/autogen/tri_mesh/valid_index_from_tuple.hpp b/src/wmtk/autogen/tri_mesh/valid_index_from_tuple.hpp new file mode 100644 index 0000000000..0a75d9d405 --- /dev/null +++ b/src/wmtk/autogen/tri_mesh/valid_index_from_tuple.hpp @@ -0,0 +1,12 @@ + +#pragma once +// DO NOT MODIFY, autogenerated from the /scripts directory +#include + +namespace wmtk::autogen::tri_mesh { +int8_t valid_index_from_tuple(const Tuple& t); + +} + +#include "valid_index_from_tuple.hxx" +# \ No newline at end of file diff --git a/src/wmtk/autogen/tri_mesh/valid_index_from_tuple.hxx b/src/wmtk/autogen/tri_mesh/valid_index_from_tuple.hxx new file mode 100644 index 0000000000..38d29b7ffc --- /dev/null +++ b/src/wmtk/autogen/tri_mesh/valid_index_from_tuple.hxx @@ -0,0 +1,16 @@ + +#pragma once +// DO NOT MODIFY, autogenerated from the /scripts directory +#include "autogenerated_tables.hpp" +#include "local_id_table_offset.hpp" +#include "valid_index_from_tuple.hpp" +namespace wmtk::autogen::tri_mesh { +inline int8_t valid_index_from_tuple(const Tuple& t) +{ + { + const int64_t offset = local_id_table_offset(t); + const int8_t valid_index = auto_all_to_valid_tuple_indices[offset]; + return valid_index; + } +} +} // namespace wmtk::autogen::tri_mesh diff --git a/src/wmtk/autogen/tuple_from_valid_index.cpp b/src/wmtk/autogen/tuple_from_valid_index.cpp new file mode 100644 index 0000000000..982422cc84 --- /dev/null +++ b/src/wmtk/autogen/tuple_from_valid_index.cpp @@ -0,0 +1,25 @@ + +#include "tuple_from_valid_index.hpp" +#include +#include +#include +#include +namespace wmtk::autogen { +Tuple tuple_from_valid_index( + PrimitiveType mesh_type, + const int64_t global_cid, + int8_t valid_tuple_index) +{ + switch (mesh_type) { + case PrimitiveType::Tetrahedron: + return tet_mesh::tuple_from_valid_index(global_cid, valid_tuple_index); + case PrimitiveType::Triangle: + return tri_mesh::tuple_from_valid_index(global_cid, valid_tuple_index); + case PrimitiveType::Edge: + return edge_mesh::tuple_from_valid_index(global_cid, valid_tuple_index); + case PrimitiveType::Vertex: return Tuple(-1, -1, -1, global_cid); + default: assert(false); // "not implemented" + } + return {}; +} +} // namespace wmtk::autogen diff --git a/src/wmtk/autogen/tuple_from_valid_index.hpp b/src/wmtk/autogen/tuple_from_valid_index.hpp new file mode 100644 index 0000000000..87f67ba384 --- /dev/null +++ b/src/wmtk/autogen/tuple_from_valid_index.hpp @@ -0,0 +1,14 @@ + + +#pragma once +#include +#include + +// NOTE: this header primarily exists to simplify unit testing, not really for use +namespace wmtk::autogen { +Tuple tuple_from_valid_index( + PrimitiveType mesh_type, + const int64_t global_cid, + int8_t valid_tuple_index); + +} // namespace wmtk::autogen diff --git a/src/wmtk/autogen/valid_index_from_tuple.cpp b/src/wmtk/autogen/valid_index_from_tuple.cpp new file mode 100644 index 0000000000..ad0014132b --- /dev/null +++ b/src/wmtk/autogen/valid_index_from_tuple.cpp @@ -0,0 +1,19 @@ + +#include "valid_index_from_tuple.hpp" +#include +#include +#include +#include +namespace wmtk::autogen { +int8_t valid_index_from_tuple(PrimitiveType mesh_type, const Tuple& t) +{ + switch (mesh_type) { + case PrimitiveType::Tetrahedron: return tet_mesh::valid_index_from_tuple(t); + case PrimitiveType::Triangle: return tri_mesh::valid_index_from_tuple(t); + case PrimitiveType::Edge: return edge_mesh::valid_index_from_tuple(t); + case PrimitiveType::Vertex: + default: return 0; + } + return {}; +} +} // namespace wmtk::autogen diff --git a/src/wmtk/autogen/valid_index_from_tuple.hpp b/src/wmtk/autogen/valid_index_from_tuple.hpp new file mode 100644 index 0000000000..01d86c9848 --- /dev/null +++ b/src/wmtk/autogen/valid_index_from_tuple.hpp @@ -0,0 +1,8 @@ +#pragma once +#include + +namespace wmtk::autogen { +int8_t valid_index_from_tuple(PrimitiveType mesh_type, const Tuple& t); + +} // namespace wmtk::autogen + diff --git a/src/wmtk/multimesh/utils/CMakeLists.txt b/src/wmtk/multimesh/utils/CMakeLists.txt index 71087367bd..fa2092cc9e 100644 --- a/src/wmtk/multimesh/utils/CMakeLists.txt +++ b/src/wmtk/multimesh/utils/CMakeLists.txt @@ -1,10 +1,12 @@ set(SRC_FILES find_local_switch_sequence.cpp - local_switch_tuple.cpp - transport_tuple.cpp find_local_switch_sequence.hpp + find_local_dart_action.cpp + find_local_dart_action.hpp + local_switch_tuple.cpp local_switch_tuple.hpp + transport_tuple.cpp transport_tuple.hpp tuple_map_attribute_io.hpp diff --git a/src/wmtk/multimesh/utils/find_local_dart_action.cpp b/src/wmtk/multimesh/utils/find_local_dart_action.cpp new file mode 100644 index 0000000000..4ad1710724 --- /dev/null +++ b/src/wmtk/multimesh/utils/find_local_dart_action.cpp @@ -0,0 +1,29 @@ + +#include "find_local_dart_action.hpp" + +#include +#include +#include +#include +#include +#include "local_switch_tuple.hpp" +namespace wmtk::multimesh::utils { +int8_t find_local_dart_action(PrimitiveType pt, const Tuple& source, const Tuple& target) +{ + wmtk::autogen::SimplexDart sd(pt); + return find_local_dart_action(sd, source, target); +} +int8_t find_local_dart_action( + const wmtk::autogen::SimplexDart& sd, + const Tuple& source, + const Tuple& target) +{ + // target = R * source + // target * source^{-1} = R + int8_t src = sd.valid_index_from_tuple(source); + int8_t tgt = sd.valid_index_from_tuple(target); + int8_t src_inv = sd.inverse(src); + return sd.product(tgt, src_inv); +} + +} // namespace wmtk::multimesh::utils diff --git a/src/wmtk/multimesh/utils/find_local_dart_action.hpp b/src/wmtk/multimesh/utils/find_local_dart_action.hpp new file mode 100644 index 0000000000..a50cc40d25 --- /dev/null +++ b/src/wmtk/multimesh/utils/find_local_dart_action.hpp @@ -0,0 +1,19 @@ +#pragma once +#include +#include +#include +namespace wmtk::autogen { +class SimplexDart; +} + +namespace wmtk::multimesh::utils { + +// Maps the tuple source according to the operation sequence +// std::vector operations where operations satisfies +// base_target = switch_tuples(base_source, operations) +int8_t find_local_dart_action(PrimitiveType mesh_type, const Tuple& source, const Tuple& target); +int8_t find_local_dart_action( + const wmtk::autogen::SimplexDart& sd, + const Tuple& source, + const Tuple& target); +} // namespace wmtk::multimesh::utils diff --git a/src/wmtk/multimesh/utils/transport_tuple.cpp b/src/wmtk/multimesh/utils/transport_tuple.cpp index aa002c08fa..860439f570 100644 --- a/src/wmtk/multimesh/utils/transport_tuple.cpp +++ b/src/wmtk/multimesh/utils/transport_tuple.cpp @@ -1,11 +1,15 @@ #include "transport_tuple.hpp" +#include +#include #include +#include "find_local_dart_action.hpp" #include "find_local_switch_sequence.hpp" #include "local_switch_tuple.hpp" namespace wmtk::multimesh::utils { -Tuple transport_tuple( +namespace internal { +Tuple transport_tuple_sequence( const Tuple& base_source, const Tuple& base_target, PrimitiveType base_primitive_type, @@ -14,6 +18,61 @@ Tuple transport_tuple( { std::vector operations = find_local_switch_sequence(base_source, base_target, base_primitive_type); + return local_switch_tuples(primitive_type, source, operations); } +Tuple transport_tuple_dart( + const Tuple& base_source, + const Tuple& base_target, + PrimitiveType base_primitive_type, + const Tuple& source, + PrimitiveType primitive_type) +{ + wmtk::autogen::SimplexDart base_sd(base_primitive_type); + wmtk::autogen::SimplexDart sd(primitive_type); + return transport_tuple(base_sd, sd, base_source, base_target, source); +} +} // namespace internal +Tuple transport_tuple( + const Tuple& base_source, + const Tuple& base_target, + PrimitiveType base_primitive_type, + const Tuple& source, + PrimitiveType primitive_type) +{ + auto dart = internal::transport_tuple_dart( + base_source, + base_target, + base_primitive_type, + source, + primitive_type); + + + /* + auto seq = internal::transport_tuple_sequence( + base_source, + base_target, + base_primitive_type, + source, + primitive_type); + assert( dart == seq); + */ + return dart; +} + +Tuple transport_tuple( + const wmtk::autogen::SimplexDart& base_sd, + const wmtk::autogen::SimplexDart& sd, + const Tuple& base_source, + const Tuple& base_target, + const Tuple& source) +{ + const int8_t base_action = find_local_dart_action(base_sd, base_source, base_target); + const int8_t action = base_sd.convert(base_action, sd); + + + int8_t src_dart = sd.valid_index_from_tuple(source); + const int8_t tgt_dart = sd.product(action, src_dart); + return sd.update_tuple_from_valid_index(source, tgt_dart); +} } // namespace wmtk::multimesh::utils diff --git a/src/wmtk/multimesh/utils/transport_tuple.hpp b/src/wmtk/multimesh/utils/transport_tuple.hpp index e2ae185a6a..f5f04882b7 100644 --- a/src/wmtk/multimesh/utils/transport_tuple.hpp +++ b/src/wmtk/multimesh/utils/transport_tuple.hpp @@ -2,7 +2,25 @@ #include #include +namespace wmtk::autogen { +class SimplexDart; +} namespace wmtk::multimesh::utils { +namespace internal { + +Tuple transport_tuple_sequence( + const Tuple& base_source, + const Tuple& base_target, + PrimitiveType base_primitive_type, + const Tuple& source, + PrimitiveType primitive_type); +Tuple transport_tuple_dart( + const Tuple& base_source, + const Tuple& base_target, + PrimitiveType base_primitive_type, + const Tuple& source, + PrimitiveType primitive_type); +} // namespace internal // Maps the tuple source according to the operation sequence // std::vector operations where operations satisfies @@ -15,4 +33,11 @@ Tuple transport_tuple( PrimitiveType base_primitive_type, const Tuple& source, PrimitiveType primitive_type); + +Tuple transport_tuple( + const wmtk::autogen::SimplexDart& base_sd, + const wmtk::autogen::SimplexDart& sd, + const Tuple& base_source, + const Tuple& base_target, + const Tuple& source); } // namespace wmtk::multimesh::utils diff --git a/src/wmtk/utils/TupleInspector.hpp b/src/wmtk/utils/TupleInspector.hpp index b86730c088..bf6fb1266d 100644 --- a/src/wmtk/utils/TupleInspector.hpp +++ b/src/wmtk/utils/TupleInspector.hpp @@ -1,5 +1,7 @@ #pragma once +#include #include +#include #include @@ -12,6 +14,17 @@ class TupleInspector static int64_t local_eid(const Tuple& t) { return t.m_local_eid; } static int64_t local_fid(const Tuple& t) { return t.m_local_fid; } + static int64_t local_id(const PrimitiveType pt, const Tuple& t) + { + switch (pt) { + case PrimitiveType::Triangle: return local_fid(t); + case PrimitiveType::Edge: return local_eid(t); + case PrimitiveType::Vertex: return local_vid(t); + case PrimitiveType::Tetrahedron: assert(false); + default: return -1; + } + } + static int64_t global_cid(const Tuple& t) { return t.m_global_cid; } static int64_t hash(const Tuple& t) { return t.m_hash; } static std::string as_string(const Tuple& t); diff --git a/src/wmtk/utils/array_to_map.hpp b/src/wmtk/utils/array_to_map.hpp new file mode 100644 index 0000000000..2d7c683b53 --- /dev/null +++ b/src/wmtk/utils/array_to_map.hpp @@ -0,0 +1,25 @@ +#pragma once + +namespace wmtk::utils { + +template +auto array_to_map(const T (&a)[R][C]) +{ + return typename Eigen::Matrix::ConstMapType(a); +} +template +auto array_to_map(T (&a)[R][C]) +{ + return typename Eigen::Matrix::MapType(a); +} +template +auto array_to_map(const T (&a)[R]) +{ + return typename Eigen::Matrix::ConstMapType(a); +} +template +auto array_to_map(T (&a)[R]) +{ + return typename Eigen::Matrix::MapType(a); +} +} // namespace wmtk::utils diff --git a/tests/multimesh/CMakeLists.txt b/tests/multimesh/CMakeLists.txt index 5c8484a920..cf62cb2158 100644 --- a/tests/multimesh/CMakeLists.txt +++ b/tests/multimesh/CMakeLists.txt @@ -9,5 +9,6 @@ set(TEST_SOURCES test_multi_mesh_boundary.cpp consolidate.cpp test_ids.cpp + transport_tuple.cpp ) target_sources(wmtk_tests PRIVATE ${TEST_SOURCES}) diff --git a/tests/multimesh/transport_tuple.cpp b/tests/multimesh/transport_tuple.cpp new file mode 100644 index 0000000000..bfafc8d378 --- /dev/null +++ b/tests/multimesh/transport_tuple.cpp @@ -0,0 +1,108 @@ + +#include +#include +#include +#include +#include +#include +#include "tools/all_valid_local_tuples.hpp" +#include "wmtk/multimesh/utils/find_local_dart_action.hpp" + +using namespace wmtk; +using namespace wmtk::tests; + +TEST_CASE("transport_tuple", "[tuple][multimesh]") +{ + // when other meshes are available add them here + for (PrimitiveType base_mesh_type : + {PrimitiveType::Edge, PrimitiveType::Triangle, PrimitiveType::Tetrahedron}) { + autogen::SimplexDart base_sd(base_mesh_type); + + auto base_all_tuples = all_valid_local_tuples(base_mesh_type); + for (PrimitiveType mesh_type : + {PrimitiveType::Edge, PrimitiveType::Triangle, PrimitiveType::Tetrahedron}) { + auto all_tuples = all_valid_local_tuples(mesh_type); + autogen::SimplexDart sd(mesh_type); + + for (const auto& base_source : base_all_tuples) { + for (const auto& base_target : base_all_tuples) { + const int8_t base_action = wmtk::multimesh::utils::find_local_dart_action( + base_sd, + base_source, + base_target); + /* + spdlog::warn( + "Base action: {}={}>{}", + wmtk::utils::TupleInspector::as_string(base_source), + base_action, + wmtk::utils::TupleInspector::as_string(base_target)); + */ + + + if (base_mesh_type >= mesh_type) { + bool same_face = true; + for (PrimitiveType pt : utils::primitive_range(mesh_type, base_mesh_type)) { + if (pt == base_mesh_type) { + continue; + } + // only' map between things where a map exists + if (wmtk::utils::TupleInspector::local_id(pt, base_source) != + wmtk::utils::TupleInspector::local_id(pt, base_target)) { + same_face = false; + break; + } + } + if (!same_face) { + continue; + } + for (const auto& source : all_tuples) { + wmtk::Tuple sequence_res = + wmtk::multimesh::utils::internal::transport_tuple_sequence( + base_source, + base_target, + base_mesh_type, + source, + mesh_type); + wmtk::Tuple dart_res = + wmtk::multimesh::utils::internal::transport_tuple_dart( + base_source, + base_target, + base_mesh_type, + source, + mesh_type); + const int8_t seq_action = + wmtk::multimesh::utils::find_local_dart_action( + sd, + source, + sequence_res); + const int8_t action = wmtk::multimesh::utils::find_local_dart_action( + sd, + source, + dart_res); + /* + spdlog::info( + "Sequence action: {}={}>{}", + wmtk::utils::TupleInspector::as_string(source), + seq_action, + wmtk::utils::TupleInspector::as_string(sequence_res)); + + spdlog::info( + "Dart action: {}={}>{}", + wmtk::utils::TupleInspector::as_string(source), + action, + wmtk::utils::TupleInspector::as_string(dart_res)); + */ + + CHECK(seq_action == action); + CHECK(base_sd.convert(base_action, sd) == action); + + CHECK(sequence_res == dart_res); + + continue; + } + } + } + } + } + } +} diff --git a/tests/test_autogen.cpp b/tests/test_autogen.cpp index 8beee97aac..7cccea7a39 100644 --- a/tests/test_autogen.cpp +++ b/tests/test_autogen.cpp @@ -1,9 +1,11 @@ +#include #include #include #include #include #include #include +#include #include #include #include @@ -34,55 +36,59 @@ TEST_CASE("tuple_autogen_sizes", "[tuple]") auto get_array_range = [](const auto& array) -> std::array { return std::array{{array, array + std::size(array)}}; }; - {// ccw check - {// tri - auto ccw_range = get_array_range(tri_mesh::auto_2d_table_ccw); - size_t count = std::count_if(ccw_range[0], ccw_range[1], [](int64_t v) { return v != -1; }); - CHECK(count == valid_face); -} -{ - auto ccw_range = get_array_range(tet_mesh::auto_3d_table_ccw); - size_t count = std::count_if(ccw_range[0], ccw_range[1], [](int64_t v) { return v != -1; }); - CHECK(count == valid_tet); -} -} -{{// tri - auto range = get_array_range(tri_mesh::auto_2d_table_vertex); -size_t count = - std::count_if(range[0], range[1], [](const int64_t v[2]) { return v[0] != -1 && v[1] != -1; }); -CHECK(count == valid_face); -} -{ // tri - auto range = get_array_range(tri_mesh::auto_2d_table_edge); - size_t count = std::count_if(range[0], range[1], [](const int64_t v[2]) { - return v[0] != -1 && v[1] != -1; - }); - CHECK(count == valid_face); -} -} -{ - { // tet - auto range = get_array_range(tet_mesh::auto_3d_table_vertex); - size_t count = std::count_if(range[0], range[1], [](const int64_t v[3]) { - return v[0] != -1 && v[1] != -1 && v[2] != -1; - }); - CHECK(count == valid_tet); - } - { // tet - auto range = get_array_range(tet_mesh::auto_3d_table_edge); - size_t count = std::count_if(range[0], range[1], [](const int64_t v[3]) { - return v[0] != -1 && v[1] != -1 && v[2] != -1; - }); - CHECK(count == valid_tet); - } - { // tet - auto range = get_array_range(tet_mesh::auto_3d_table_face); - size_t count = std::count_if(range[0], range[1], [](const int64_t v[3]) { - return v[0] != -1 && v[1] != -1 && v[2] != -1; - }); - CHECK(count == valid_tet); + { // ccw check + { // tri + auto ccw_range = get_array_range(tri_mesh::auto_2d_table_ccw); + size_t count = + std::count_if(ccw_range[0], ccw_range[1], [](int64_t v) { return v != -1; }); + CHECK(count == valid_face); + } + { + auto ccw_range = get_array_range(tet_mesh::auto_3d_table_ccw); + size_t count = + std::count_if(ccw_range[0], ccw_range[1], [](int64_t v) { return v != -1; }); + CHECK(count == valid_tet); + } + } + { + { // tri + auto range = get_array_range(tri_mesh::auto_2d_table_vertex); + size_t count = std::count_if(range[0], range[1], [](const int64_t v[2]) { + return v[0] != -1 && v[1] != -1; + }); + CHECK(count == valid_face); + } + { // tri + auto range = get_array_range(tri_mesh::auto_2d_table_edge); + size_t count = std::count_if(range[0], range[1], [](const int64_t v[2]) { + return v[0] != -1 && v[1] != -1; + }); + CHECK(count == valid_face); + } + } + { + { // tet + auto range = get_array_range(tet_mesh::auto_3d_table_vertex); + size_t count = std::count_if(range[0], range[1], [](const int64_t v[3]) { + return v[0] != -1 && v[1] != -1 && v[2] != -1; + }); + CHECK(count == valid_tet); + } + { // tet + auto range = get_array_range(tet_mesh::auto_3d_table_edge); + size_t count = std::count_if(range[0], range[1], [](const int64_t v[3]) { + return v[0] != -1 && v[1] != -1 && v[2] != -1; + }); + CHECK(count == valid_tet); + } + { // tet + auto range = get_array_range(tet_mesh::auto_3d_table_face); + size_t count = std::count_if(range[0], range[1], [](const int64_t v[3]) { + return v[0] != -1 && v[1] != -1 && v[2] != -1; + }); + CHECK(count == valid_tet); + } } -} } TEST_CASE("tuple_autogen_id_inversion", "[tuple]") @@ -144,7 +150,7 @@ TEST_CASE("tuple_autogen_local_id_inversion", "[tuple]") for (const auto& t : tuples) { int64_t id = tri_mesh::local_id_table_offset(t); auto [lvid, leid] = tri_mesh::lvid_leid_from_table_offset(id); - Tuple nt(lvid, leid, 0, 0, 0); + Tuple nt(lvid, leid, -1, 0, -1); int64_t nid = tri_mesh::local_id_table_offset(nt); CHECK(t == nt); @@ -157,7 +163,7 @@ TEST_CASE("tuple_autogen_local_id_inversion", "[tuple]") for (const auto& t : tuples) { int64_t id = tet_mesh::local_id_table_offset(t); auto [lvid, leid, lfid] = tet_mesh::lvid_leid_lfid_from_table_offset(id); - Tuple nt(lvid, leid, lfid, 0, 0); + Tuple nt(lvid, leid, lfid, 0, -1); int64_t nid = tet_mesh::local_id_table_offset(nt); CHECK(t == nt); CHECK(id == nid); @@ -204,7 +210,8 @@ TEST_CASE("tuple_autogen_ptype_local_switch_tuple_equivalent", "[tuple]") TEST_CASE("tuple_autogen_switch_still_valid", "[tuple]") { // when other meshes are available add them here - for (PrimitiveType mesh_type : {PrimitiveType::Triangle /*, PrimitiveType::Tetrahedron*/}) { + for (PrimitiveType mesh_type : + {PrimitiveType::Edge, PrimitiveType::Triangle, PrimitiveType::Tetrahedron}) { auto tuples = all_valid_local_tuples(mesh_type); for (const auto& t : tuples) { @@ -216,3 +223,191 @@ TEST_CASE("tuple_autogen_switch_still_valid", "[tuple]") } } } +TEST_CASE("tuple_autogen_index_dart_tuple_conversion", "[tuple]") +{ + // when other meshes are available add them here + for (PrimitiveType mesh_type : + {PrimitiveType::Edge, PrimitiveType::Triangle, PrimitiveType::Tetrahedron}) { + auto tuples = all_valid_local_tuples(mesh_type); + autogen::SimplexDart sd(mesh_type); + + for (const auto& t : tuples) { + int8_t i = sd.valid_index_from_tuple(t); + Tuple nt = sd.tuple_from_valid_index(0, i); + + CHECK(t == nt); + } + } +} + +TEST_CASE("tuple_autogen_index_dart_group_structure", "[tuple]") +{ + // when other meshes are available add them here + for (PrimitiveType mesh_type : + {PrimitiveType::Edge, PrimitiveType::Triangle, PrimitiveType::Tetrahedron}) { + autogen::SimplexDart sd(mesh_type); + assert(size_t(sd.valid_indices().size()) == sd.size()); + + for (PrimitiveType pt : primitives_up_to(mesh_type)) { + const int8_t index_switch = sd.primitive_as_index(pt); + CHECK(sd.identity() == sd.product(index_switch, index_switch)); + CHECK(index_switch == sd.inverse(index_switch)); + } + for (int8_t index = 0; index < sd.size(); ++index) { + const int8_t inv = sd.inverse(index); + CHECK(sd.product(index, inv) == sd.identity()); + CHECK(sd.product(inv, index) == sd.identity()); + // for (int8_t index2 = 0; index2 < sd.size(); ++index2) { + // const int8_t inv2 = sd.inverse(index2); + // const int8_t p = sd.product(index, index2); + // const int8_t pi = sd.product(inv2, inv); + // CHECK(pi == sd.inverse(p)); + // CHECK(sd.product(p, pi) == sd.identity()); + // CHECK(sd.product(pi, p) == sd.identity()); + // } + } + } +} + + +TEST_CASE("tuple_autogen_index_dart_vs_switch", "[tuple]") +{ + // when other meshes are available add them here + for (PrimitiveType mesh_type : + {PrimitiveType::Edge, PrimitiveType::Triangle, PrimitiveType::Tetrahedron}) { + auto tuples = all_valid_local_tuples(mesh_type); + autogen::SimplexDart sd(mesh_type); + + for (const auto& t : tuples) { + CHECK(tuple_is_valid_for_ccw(mesh_type, t)); + int8_t tuple_as_index = sd.valid_index_from_tuple(t); + for (PrimitiveType pt : primitives_up_to(mesh_type)) { + Tuple manual_switch = local_switch_tuple(mesh_type, t, pt); + + const int8_t index_switch = sd.primitive_as_index(pt); + + Tuple table_switch = local_switch_tuple(mesh_type, t, index_switch); + + CHECK(manual_switch == table_switch); + } + } + } +} + +TEST_CASE("tuple_autogen_products_vs_switch", "[tuple]") +{ + // when other meshes are available add them here + for (PrimitiveType mesh_type : + {PrimitiveType::Edge, PrimitiveType::Triangle, PrimitiveType::Tetrahedron}) { + auto tuples = all_valid_local_tuples(mesh_type); + + std::vector sequence; + + autogen::SimplexDart sd(mesh_type); + + + for (const auto& t : tuples) { + CHECK(tuple_is_valid_for_ccw(mesh_type, t)); + auto run = [&]() { + Tuple manual_switch = t; + const int8_t initial_index = sd.valid_index_from_tuple(t); + int8_t index = initial_index; + int8_t op = sd.identity(); + ; + + std::vector seq_tups; + for (const auto& s : sequence) { + manual_switch = local_switch_tuple(mesh_type, manual_switch, s); + seq_tups.emplace_back(sd.primitive_as_index(s)); + op = sd.product(sd.primitive_as_index(s), op); + index = sd.product(sd.primitive_as_index(s), index); + } + + Tuple product_switch = sd.update_tuple_from_valid_index(t, index); + Tuple product_switch2 = + sd.update_tuple_from_valid_index(t, sd.product(op, initial_index)); + + CHECK(manual_switch == product_switch); + CHECK(product_switch == product_switch2); + }; + for (size_t j = 0; j < 4; ++j) { + for (PrimitiveType pt0 : primitives_up_to(mesh_type)) { + sequence.clear(); + sequence.emplace_back(pt0); + if (j == 0) { + run(); + continue; + } + for (PrimitiveType pt1 : primitives_up_to(mesh_type)) { + sequence.emplace_back(pt0); + if (j == 1) { + run(); + continue; + } + for (PrimitiveType pt2 : primitives_up_to(mesh_type)) { + sequence.emplace_back(pt0); + if (j == 2) { + run(); + continue; + } + for (PrimitiveType pt3 : primitives_up_to(mesh_type)) { + sequence.emplace_back(pt0); + if (j == 3) { + run(); + continue; + } + for (PrimitiveType pt4 : primitives_up_to(mesh_type)) { + sequence.emplace_back(pt0); + if (j == 4) { + run(); + continue; + } + } + } + } + } + } + } + } + } +} + +TEST_CASE("tuple_autogen_index_dart_map_between_simplices", "[tuple]") +{ + // when other meshes are available add them here + for (PrimitiveType mesh_type : + {PrimitiveType::Edge, PrimitiveType::Triangle, PrimitiveType::Tetrahedron}) { + autogen::SimplexDart sd(mesh_type); + for (PrimitiveType mesh_type2 : + {PrimitiveType::Edge, PrimitiveType::Triangle, PrimitiveType::Tetrahedron}) { + if (mesh_type > mesh_type2) { + continue; + } + + autogen::SimplexDart sd2(mesh_type2); + for (int8_t index = 0; index < sd.size(); ++index) { + REQUIRE(sd.convert(index, sd2) != -1); + REQUIRE(sd2.convert(sd.convert(index, sd2), sd) == index); + } + + for (int8_t index = 0; index < sd.size(); ++index) { + const int8_t inv = sd.inverse(index); + + int8_t index2 = sd.convert(index, sd2); + int8_t inv2 = sd.convert(inv, sd2); + CHECK(sd2.product(index2, inv2) == sd2.identity()); + } + for (int8_t index = 0; index < sd.size(); ++index) { + for (int8_t index_ = 0; index_ < sd.size(); ++index_) { + int8_t p = sd.product(index, index_); + + + int8_t index2 = sd.convert(index, sd2); + int8_t index_2 = sd.convert(index_, sd2); + int8_t p2 = sd2.product(index2, index_2); + CHECK(sd.convert(p, sd2) == p2); + } + } + } + } +} diff --git a/tests/tools/all_valid_local_tuples.cpp b/tests/tools/all_valid_local_tuples.cpp index 226c91932f..c89415c3b6 100644 --- a/tests/tools/all_valid_local_tuples.cpp +++ b/tests/tools/all_valid_local_tuples.cpp @@ -1,5 +1,6 @@ #include "all_valid_local_tuples.hpp" #include +#include #include #include #include @@ -41,7 +42,7 @@ int64_t max_tuple_count(PrimitiveType pt) Tuple tuple_from_offset_id(PrimitiveType pt, int offset) { - int64_t lvid = 0, leid = 0, lfid = 0, gcid = 0, hash = 0; + int64_t lvid = -1, leid = -1, lfid = -1, gcid = -1, hash = -1; switch (pt) { case PrimitiveType::Triangle: { @@ -61,28 +62,22 @@ Tuple tuple_from_offset_id(PrimitiveType pt, int offset) } Tuple r(lvid, leid, lfid, gcid, hash); - if (!tuple_is_valid_for_ccw(pt, r)) { - r = Tuple(); - } + // if (!tuple_is_valid_for_ccw(pt, r)) { + // r = Tuple(); + // } return r; } std::vector all_valid_local_tuples(PrimitiveType pt) { + wmtk::autogen::SimplexDart sd(pt); std::vector tups; - int64_t size = max_tuple_count(pt); - assert(size > 0); + size_t size = sd.size(); tups.reserve(size); - for (int64_t idx = 0; idx < max_tuple_count(pt); ++idx) { - tups.emplace_back(tuple_from_offset_id(pt, idx)); + for (int8_t idx = 0; idx < size; ++idx) { + tups.emplace_back(sd.tuple_from_valid_index(0, idx)); } - tups.erase( - std::remove_if( - tups.begin(), - tups.end(), - [](const Tuple& t) -> bool { return t.is_null(); }), - tups.end()); return tups; } } // namespace wmtk::tests