isoAM_with_neumann code path#
This page summarizes the code path executed when calling
mesh.geometry.isoAM_with_neumann to compute IsoAM with Neumann handling.
Overview#
It computes IsoAM (Isotropic Anisotropic Metric) with Neumann boundary effects. The routine uses a point adjacency graph, weights, surface normals, and a moment matrix to assemble raw AM and then the gradient operator.
Entry point:
mesh.geometry.isoAM_with_neumann(...)(user API)Implementation:
graphlow.geometry.operator.isoAM_with_neumann(mesh, ...)Key dependencies:
topology.point_adjacency(),_compute_normals_on_surface_points(internally usesextract_surface,face_normals,map_cell_to_point),_compute_moment_matrix,_compute_rawAM_and_moment_inv,_create_grad_operator_from
Call flow#
flowchart TB
subgraph User["User API"]
A["isoAM_with_neumann"]
end
subgraph Core["src/graphlow/core/geometry.py"]
B["MeshGeometry.isoAM_with_neumann"]
B --> C["_isoAM_with_neumann"]
end
subgraph Operator["src/graphlow/geometry/operator.py"]
D["isoAM_with_neumann"]
ADJ["point_adjacency"]
W["weights"]
NORM["_compute_normals_on_surface_points"]
MOM["_compute_moment_matrix"]
RAW["_compute_rawAM_and_moment_inv"]
GRAD["_create_grad_operator_from"]
D --> ADJ
D --> W
D --> NORM
D --> MOM
D --> RAW
D --> GRAD
end
subgraph Topology["src/graphlow/core/topology.py"]
ADJ_IMPL["point_adjacency"]
GET_SKEL["get_skeleton"]
BCACHE["bcache.sparse"]
ADJ_IMPL --> GET_SKEL
GET_SKEL --> BCACHE
MAP_CP["map_cell_to_point"]
end
subgraph SkeletonBuilder["src/graphlow/graph/skeleton_builder.py"]
BUILD_PP["_build_pp"]
end
subgraph NormalsHelper["inside operator.py"]
EXTRACT["extract_surface"]
FACE_N["face_normals"]
MAP_N["map_cell_to_point"]
NORM_SCATTER["normalize, scatter_add_to_parent_point_data"]
EXTRACT --> FACE_N
FACE_N --> MAP_N
MAP_N --> NORM_SCATTER
end
subgraph ExtractSurface["src/graphlow/core/mesh.py"]
PV_EXT["TensorMesh.extract_surface"]
end
subgraph SurfaceGeo["src/graphlow/geometry/surface.py"]
FN["face_normals"]
FN --> SURF_FN["face_normals"]
end
subgraph Mapping["src/graphlow/graph/mapping.py"]
MAP_CP_IMPL["map_cell_to_point"]
end
subgraph Moment["inside operator.py"]
DIFF["_compute_moment_matrix"]
OUTER["u⊗u index_add"]
DIFF --> OUTER
end
subgraph RawAM["inside operator.py"]
SOLVE["_compute_rawAM_and_moment_inv"]
PACK["Cholesky solve, pack sparse"]
SOLVE --> PACK
end
subgraph GradOp["inside operator.py"]
ROWSUM["_create_grad_operator_from"]
DIAG["row-sum-zero"]
ROWSUM --> DIAG
end
A --> B
C --> D
ADJ --> ADJ_IMPL
GET_SKEL --> BUILD_PP
W --> MAP_CP
MAP_CP --> MAP_CP_IMPL
NORM --> EXTRACT
EXTRACT --> PV_EXT
FACE_N --> FN
MAP_N --> MAP_CP_IMPL
D --> RAW
MOM --> RAW
RAW --> GRAD
Simplified sequence diagram#
This diagram shows the path when consider_volume=True.
sequenceDiagram
participant U as User
participant Core as core/geometry.py
participant Op as geometry/operator.py
participant Topo as core/topology.py
participant Skel as graph/skeleton_builder.py
participant Mesh as core/mesh.py
participant Surf as geometry/surface.py
participant Map as graph/mapping.py
U->>Core: isoAM_with_neumann
Core->>Op: _isoAM_with_neumann
Op->>Topo: point_adjacency
Topo->>Skel: get_skeleton
Skel->>Skel: _build_pp
Topo->>Op: adj
Op->>Core: cell_volumes
Core-->>Op: volumes
Op->>Topo: map_cell_to_point
Topo->>Map: map_cell_to_point
Map-->>Op: weights
Op->>Op: _compute_normals_on_surface_points
Op->>Mesh: extract_surface
Mesh-->>Op: surf
Op->>Surf: face_normals
Surf-->>Op: normals_on_faces
Op->>Topo: map_cell_to_point
Topo->>Map: map_cell_to_point
Map-->>Op: normals_on_points
Op->>Mesh: scatter_add_to_parent_point_data
Mesh-->>Op: normals_on_surface_points
Op->>Op: _compute_moment_matrix
Op-->>Op: moment_matrix
Op->>Op: _compute_rawAM_and_moment_inv
Op-->>Op: rawAM, moment_inv
Op->>Op: _create_grad_operator_from
Op-->>Op: NisoAM
Op-->>Core: NisoAM, weighted_normals, moment_inv
Core-->>U: isoam, weighted_normals, moment_inv
File and symbol mapping#
Role |
File |
Main symbols |
|---|---|---|
User API |
(usage code) |
|
Geometry wrapper |
|
|
IsoAM implementation |
|
|
Topology |
|
|
Skeleton construction |
|
|
Surface extraction |
|
|
Face normals |
|
|
Cell-to-point mapping |
|
|
Notes#
PP: Point-to-point adjacency (vertex pairs connected by an edge). It is cached via
get_skeleton(PP)and converted to backend sparse COO bybcache.sparse(..., "coo").consider_volume=True: Only in this mode,
cell_volumes()andmap_cell_to_point(volumes, ...)are used, and their result becomes vertex weights.normals_on_surface_points: Normals are nonzero only on the surface of the volume mesh. The flow is: extract a surface mesh with
extract_surface(), map itsface_normalsto points viamap_cell_to_point, then scatter the result back to the parent volume point space viasurf.scatter_add_to_parent_point_data(...)and normalize.moment_matrix: Weighted sum of \(u_{ij} \otimes u_{ij}\) over adjacency vectors \(u_{ij}\). In the Neumann variant,
n_otimes_n(outer product of surface normals) is added to reduce singularity risk.rawAM / NisoAM: rawAM is a scalar-weighted form of \(M_i^{-1}(x_j-x_i)\) represented as sparse COO with shape
(K, N, N)._create_grad_operator_fromconverts it into a row-sum-zero gradient operator.