88https://github.com/IngeborgGjerde/fenics-networks by Ingeborg Gjerde.
99"""
1010
11- from typing import Any , Callable , Iterable
11+ from typing import Callable , Iterable
1212
1313from mpi4py import MPI
1414
1818
1919import basix .ufl
2020import ufl
21- from dolfinx import fem , mesh
2221from dolfinx import graph as _graph
2322from dolfinx import io as _io
23+ from dolfinx import mesh
2424from networks_fenicsx import config
2525
2626__all__ = ["NetworkMesh" ]
@@ -70,7 +70,6 @@ class NetworkMesh:
7070 _submesh_facet_markers : list [mesh .MeshTags ]
7171 _edge_meshes : list [mesh .Mesh ]
7272 _edge_entity_maps : list [mesh .EntityMap ]
73- _tangent : fem .Function
7473 _bifurcation_values : npt .NDArray [np .int32 ]
7574 _boundary_values : npt .NDArray [np .int32 ]
7675 _lm_mesh : mesh .Mesh | None
@@ -223,7 +222,6 @@ def _build_mesh(
223222 self ._bifurcation_out_color = bifurcation_out_color
224223
225224 # Generate mesh
226- tangents : npt .NDArray [np .float64 ] = np .empty ((0 , self ._geom_dim ), dtype = np .float64 )
227225 if comm .rank == graph_rank :
228226 assert isinstance (graph , nx .DiGraph ), (
229227 f"No directional graph present on rank { comm .rank } "
@@ -235,24 +233,17 @@ def _build_mesh(
235233 mesh_nodes = vertex_coords .copy ()
236234 cells = []
237235 cell_markers = []
238- local_tangents = []
239236 if len (line_weights ) == 0 :
240237 for segment in cells_array :
241238 cells .append (np .array ([segment [0 ], segment [1 ]], dtype = np .int64 ))
242239 cell_markers .append (edge_coloring [(segment [0 ], segment [1 ])])
243- start = vertex_coords [segment [0 ]]
244- end = vertex_coords [segment [1 ]]
245- local_tangents .append (_compute_tangent (start , end ))
246240 else :
247241 for segment in cells_array :
248242 start_coord_pos = mesh_nodes .shape [0 ]
249243 start = vertex_coords [segment [0 ]]
250244 end = vertex_coords [segment [1 ]]
251245 internal_line_coords = start * (1 - line_weights ) + end * line_weights
252246
253- tangent = _compute_tangent (start , end )
254- local_tangents .append (np .tile (tangent , (internal_line_coords .shape [0 ] + 1 , 1 )))
255-
256247 mesh_nodes = np .vstack ((mesh_nodes , internal_line_coords ))
257248 cells .append (np .array ([segment [0 ], start_coord_pos ], dtype = np .int64 ))
258249 segment_connectivity = (
@@ -280,12 +271,10 @@ def _build_mesh(
280271 )
281272 cells_ = np .vstack (cells ).astype (np .int64 )
282273 cell_markers_ = np .array (cell_markers , dtype = np .int32 )
283- tangents = np .vstack (local_tangents ).astype (np .float64 )
284274 else :
285275 cells_ = np .empty ((0 , 2 ), dtype = np .int64 )
286276 mesh_nodes = np .empty ((0 , self ._geom_dim ), dtype = np .float64 )
287277 cell_markers_ = np .empty ((0 ,), dtype = np .int32 )
288- tangents = tangents [:, : self ._geom_dim ].copy ()
289278 partitioner = mesh .create_cell_partitioner (mesh .GhostMode .shared_facet )
290279 graph_mesh = mesh .create_mesh (
291280 comm ,
@@ -304,10 +293,6 @@ def _build_mesh(
304293 cell_markers_ ,
305294 )
306295
307- # Distribute tangents
308- tangent_space = fem .functionspace (graph_mesh , ("DG" , 0 , (self ._geom_dim ,)))
309- self ._tangent = fem .Function (tangent_space )
310-
311296 # Which cells from the input mesh (rank 0) correspond to the local cells on this rank
312297 original_cell_indices = self .mesh .topology .original_cell_index [
313298 : self .mesh .topology .index_map (self .mesh .topology .dim ).size_local
@@ -320,26 +305,6 @@ def _build_mesh(
320305 assert isinstance (recv_counts , Iterable )
321306 assert sum (recv_counts ) == cells_ .shape [0 ]
322307
323- # Send to rank 0 which tangents that we need
324- recv_buffer : None | list [npt .NDArray [np .int64 ] | list [Any ] | MPI .Datatype ] = None
325- if comm .rank == graph_rank :
326- assert recv_counts is not None
327- recv_buffer = [np .empty (cells_ .shape [0 ], dtype = np .int64 ), recv_counts , MPI .INT64_T ]
328-
329- comm .Gatherv (sendbuf = original_cell_indices , recvbuf = recv_buffer , root = graph_rank )
330- send_t_buffer = None
331- if comm .rank == graph_rank :
332- assert recv_buffer is not None
333- recv_data = recv_buffer [0 ]
334- assert isinstance (recv_data , np .ndarray )
335- send_t_buffer = [
336- tangents [recv_data ].flatten (),
337- np .array (recv_counts ) * self ._geom_dim ,
338- ]
339-
340- comm .Scatterv (sendbuf = send_t_buffer , recvbuf = self .tangent .x .array , root = graph_rank )
341- self .tangent .x .scatter_forward ()
342-
343308 self ._subdomains = mesh .meshtags_from_entities (
344309 self .mesh ,
345310 self .mesh .topology .dim ,
@@ -459,19 +424,6 @@ def entity_maps(self):
459424 )
460425 return self ._edge_entity_maps
461426
462- @property
463- def tangent (self ):
464- """Return DG-0 field containing the tangent vector of the graph."""
465- return self ._tangent
466-
467- def export_tangent (self ):
468- if self .cfg .export :
469- with _io .XDMFFile (self .comm , self .cfg .outdir / "mesh/tangent.xdmf" , "w" ) as file :
470- file .write_mesh (self .mesh )
471- file .write_function (self .tangent )
472- else :
473- print ("Export of tangent skipped as cfg.export is set to False." )
474-
475427 @property
476428 def bifurcation_values (self ) -> npt .NDArray [np .int32 ]:
477429 return self ._bifurcation_values
@@ -485,23 +437,3 @@ def in_edges(self, bifurcation: int) -> list[int]:
485437
486438 def out_edges (self , bifurcation : int ) -> list [int ]:
487439 return self ._bifurcation_out_color [bifurcation ]
488-
489-
490- def _compute_tangent (
491- start : npt .NDArray [np .float64 ], end : npt .NDArray [np .float64 ]
492- ) -> npt .NDArray [np .float64 ]:
493- """Compute the tangent vector from start to end points.
494-
495- Tangent is oriented according to positive y-axis.
496- If perpendicular to y-axis, align with x-axis.
497-
498- Args:
499- start: Starting point coordinates.
500- end: Ending point coordinates.
501-
502- Returns:
503- Normalized tangent vector from start to end.
504- """
505- tangent = end - start
506- tangent /= np .linalg .norm (tangent , axis = - 1 )
507- return tangent
0 commit comments