def from_triangulation(cls, triangulation): """ Return a TautStructure on this triangulation. """ triangulation = t3m.Mcomplex(triangulation) # Write down the angle equations. these are normally inhomogeneous, with: # * sum(angles around edge) = 2pi, and # * sum(angles in triangle) = pi # So we add an extra dummy variable (essentially "pi") to make them homogeneous. ntets, nedges = len(triangulation.Tetrahedra), len(triangulation.Edges) angle_matrix = t3m.linalg.Matrix(nedges + ntets, 3 * ntets + 1) for i, edge in enumerate(triangulation.Edges): # Edge equations. for arrow in arrows_around(edge): t = arrow.Tetrahedron.Index q = EdgeToQuad[arrow.Edge] angle_matrix[i, 3 * t + q] += 1 angle_matrix[i, 3 * ntets] = -2 for t in range(ntets): # Triangle equations. for q in range(3): angle_matrix[nedges + t, 3 * t + q] += 1 angle_matrix[nedges + t, 3 * ntets] = -1 xrays = FXrays.find_Xrays(angle_matrix.nrows(), angle_matrix.ncols(), angle_matrix.entries(), filtering=True, print_progress=False) for xray in xrays: try: return cls(triangulation, xray) except ValueError: pass raise ValueError("Could not find taut structure on triangulation")
def peripheral_curve_package(snappy_manifold): """ Given a 1-cusped snappy_manifold M, this function returns 1. A t3m MComplex of M, and 2. the induced cusp triangulation, and 3. the dual to the cusp triangulation, and 4. two 1-cocycles on the dual cellulation which are *algebraically* dual to the peripheral framming of M. """ M = snappy_manifold assert M.num_cusps() == 1 N = t3m.Mcomplex(M) C = link.LinkSurface(N) D = dual_cellulation.DualCellulation(C) cusp_indices, data = M._get_cusp_indices_and_peripheral_curve_data() meridian = peripheral_curve_from_snappy(D, [data[i] for i in range(0, len(data), 4)]) longitude = peripheral_curve_from_snappy(D, [data[i] for i in range(2, len(data), 4)]) alpha, beta = D.integral_cohomology_basis() A = matrix([[alpha(meridian), beta(meridian)], [alpha(longitude), beta(longitude)]]) assert abs(A.det()) == 1 Ainv = A.inverse().change_ring(ZZ) B = Ainv.transpose()*matrix(ZZ, [alpha.weights, beta.weights]) mstar = dual_cellulation.OneCocycle(D, list(B[0])) lstar = dual_cellulation.OneCocycle(D, list(B[1])) AA = matrix([[mstar(meridian), lstar(meridian)], [mstar(longitude), lstar(longitude)]]) assert AA == 1 return N, C, D, (mstar, lstar)
def from_manifold_and_shapes(manifold, shapes, normalize_matrices=False, match_kernel=True): m = t3m.Mcomplex(manifold) t = TransferKernelStructuresEngine(m, manifold) t.add_shapes(shapes) t.choose_and_transfer_generators(compute_corners=True, centroid_at_origin=False) s = SpineEngine(m) s.compute_edge_info_before_ungluing() f = FundamentalPolyhedronEngine(m) f.unglue() if match_kernel: init_verts = f.init_vertices_kernel() else: init_verts = f.init_vertices() f.visit_tetrahedra_to_compute_vertices(m.ChooseGenInitialTet, init_verts) f.compute_matrices(normalize_matrices=normalize_matrices) s.add_spine_after_ungluing() return s
def from_manifold(manifold, areas=None, insphere_scale=0.05, weights=None): if manifold.solution_type() != 'all tetrahedra positively oriented': return NonGeometricRaytracingData(t3m.Mcomplex(manifold)) num_cusps = manifold.num_cusps() # Make a copy of the manifold. On the copy, we can set all # the Dehn-fillings to (0,0) so that gluing_equations gives # us both the meridian and longitude. snappy_trig = Triangulation(manifold) snappy_trig.dehn_fill(num_cusps * [(0, 0)]) # Develops the cusps of the manifold. This is needed to # compute the data for the horospheres (complete cusps) # or "Margulis tubes" (incomplete cusps). c = ComplexCuspCrossSection.fromManifoldAndShapes( manifold, manifold.tetrahedra_shapes('rect'), one_cocycle='develop') c.normalize_cusps() c.compute_translations() c.add_vertex_positions_to_horotriangles() c.lift_vertex_positions_of_horotriangles() c.move_lifted_vertex_positions_to_zero_first() # c.mcomplex is the same triangulation encoded as # t3m.Mcomplex triangulation r = IdealRaytracingData(c.mcomplex, manifold) z = c.mcomplex.Tetrahedra[0].ShapeParameters[t3m.E01] r.RF = z.real().parent() r.insphere_scale = r.RF(insphere_scale) resolved_areas = num_cusps * [1.0] if areas is None else areas r.areas = [r.RF(area) for area in resolved_areas] r.peripheral_gluing_equations = snappy_trig.gluing_equations( )[snappy_trig.num_tetrahedra():] # For debugging! Delete! r.c = c r._add_horotriangle_heights() r._add_complex_vertices() r._add_R13_vertices() r._add_O13_matrices_to_faces() r._add_R13_planes_to_faces() r._add_R13_horosphere_scales_to_vertices() r._add_cusp_to_tet_matrices() r._add_margulis_tube_ends() r._add_inspheres() r._add_log_holonomies() r._add_cusp_triangle_vertex_positions() r.add_weights(weights) return r
def compare_closed(snappy_manifold): N = snappy_manifold.filled_triangulation() T = t3m.Mcomplex(N) T.find_normal_surfaces() t_hashes = sorted(hash_t3m_surface(S) for S in T.NormalSurfaces) R = to_regina(N) r_hashes = sorted(hash_regina_surface(S) for S in vertex_surfaces(R)) all_together = sum(t_hashes, []) return t_hashes == r_hashes, len(all_together), sum(all_together)
def has_internal_singularities(tri, angle): """ Given a regina manifold tri and an angle structure (assumed to be layered), convert tri to a t3m triangulation, convert angle to the correct flipper format, use them both to get a flipper TautStructure, find the monodromy, and then check the stratum. If there are internal singularities, return True. """ # See # https://github.com/MarkCBell/flipper/blob/master/flipper/kernel/taut.py # for the relevant code in flipper T = t3m.Mcomplex(snappy.Manifold(tri)) angle_vector = angle_to_charge(angle, flipper_format=True) taut_struct = flipper.kernel.taut.TautStructure(T, angle_vector) strat = taut_struct.monodromy().stratum() return any(punc.filled for punc in strat.keys())
def complex_volumes(M, precision=53): """ Compute all complex volumes from the extended Ptolemy variety for the closed manifold M (given as Dehn-filling on 1-cusped manifold). Note: not every volume might correspond to a representation factoring through the closed manifold. In particular, we get the complex volume of the geometric representation of the cusped manifold. """ representative_ptolemys, full_var_dict = ( compute_representative_ptolemys_and_full_var_dict(M, precision)) return [[ compute_complex_volume_from_lifted_ptolemys( t3m.Mcomplex(M), lift_ptolemy_coordinates(M, sol, full_var_dict)) for sol in galois_conjugates ] for galois_conjugates in representative_ptolemys]
def test_regina(): for M in snappy.OrientableCuspedCensus(tets=8): M = t3m.Mcomplex(M) M.find_normal_surfaces(algorithm='FXrays')
def arrows_around_edges(manifold): T = t3m.Mcomplex(manifold) starts = lex_first_edge_starts(T) ans = [] return [faces_around_edge(T, tet, edge) for tet, edge in starts]
def closed_test(): for M in snappy.OrientableClosedCensus[:10]: N = M.filled_triangulation() T = t3m.Mcomplex(N) T.find_normal_surfaces() T.normal_surface_info()
def cusped_test(): for M in snappy.OrientableCuspedCensus[:10]: T = t3m.Mcomplex(M) T.find_normal_surfaces()