This page was generated from docs\source\notebooks/mesh_analysis.ipynb.

Mesh Analysis#

sigmaepsilon.mesh provides some useful classes and algorithms for mesh management and operations related to the geometry or the topology of polygonal meshes.

[1]:
import pyvista as pv
import numpy as np
from sigmaepsilon.mesh import PolyData

d, h, a = 6.0, 15.0, 15.0
cyl = pv.CylinderStructured(
    center=(0.0, 0.0, 0.0),
    direction=(0.0, 0.0, 1.0),
    radius=np.linspace(d / 2, a / 2, 15),
    height=h,
    theta_resolution=100,
    z_resolution=40,
)
mesh: PolyData = PolyData.from_pv(cyl)

Nodal Distribution Factors#

[2]:
mesh.nodal_distribution_factors()
[2]:
array([[1.        , 0.47580645, 0.23790323, ..., 0.23790323, 0.11895161,
        0.25      ],
       [0.52419355, 0.47794118, 0.23897059, ..., 0.23897059, 0.11948529,
        0.13104839],
       [0.52205882, 0.47972973, 0.23986486, ..., 0.23986486, 0.11993243,
        0.13051471],
       ...,
       [0.12807377, 0.12207031, 0.24414062, ..., 0.24414062, 0.48828125,
        0.51229508],
       [0.12792969, 0.12220149, 0.24440299, ..., 0.24440299, 0.48880597,
        0.51171875],
       [0.12779851, 0.25      , 0.5       , ..., 0.5       , 1.        ,
        0.51119403]])

Nodal Adjacency#

To access the nodal adjacency matrix as a scipy sparse matrix:

[3]:
mesh.nodal_adjacency(frmt="scipy-csr")
[3]:
<60600x60600 sparse array of type '<class 'numpy.intc'>'
        with 1527274 stored elements in Compressed Sparse Row format>
[4]:
mesh.nodal_adjacency(frmt="nx")
[4]:
<networkx.classes.graph.Graph at 0x20a5d6d3820>

as an Awkward array:

[5]:
mesh.nodal_adjacency(frmt="jagged")
[5]:
[[0, 1, 15, 16, 1515, 1516, 1530, 1531],
 [0, 1, 2, 15, 16, 17, 1515, 1516, 1517, 1530, 1531, 1532],
 [1, 2, 3, 16, 17, 18, 1516, 1517, 1518, 1531, 1532, 1533],
 [2, 3, 4, 17, 18, 19, 1517, 1518, 1519, 1532, 1533, 1534],
 [3, 4, 5, 18, 19, 20, 1518, 1519, 1520, 1533, 1534, 1535],
 [4, 5, 6, 19, 20, 21, 1519, 1520, 1521, 1534, 1535, 1536],
 [5, 6, 7, 20, 21, 22, 1520, 1521, 1522, 1535, 1536, 1537],
 [6, 7, 8, 21, 22, 23, 1521, 1522, 1523, 1536, 1537, 1538],
 [7, 8, 9, 22, 23, 24, 1522, 1523, 1524, 1537, 1538, 1539],
 [8, 9, 10, 23, 24, 25, 1523, 1524, 1525, 1538, 1539, 1540],
 ...,
 [59060, 59061, 59062, 59075, 59076, ..., 60576, 60577, 60590, 60591, 60592],
 [59061, 59062, 59063, 59076, 59077, ..., 60577, 60578, 60591, 60592, 60593],
 [59062, 59063, 59064, 59077, 59078, ..., 60578, 60579, 60592, 60593, 60594],
 [59063, 59064, 59065, 59078, 59079, ..., 60579, 60580, 60593, 60594, 60595],
 [59064, 59065, 59066, 59079, 59080, ..., 60580, 60581, 60594, 60595, 60596],
 [59065, 59066, 59067, 59080, 59081, ..., 60581, 60582, 60595, 60596, 60597],
 [59066, 59067, 59068, 59081, 59082, ..., 60582, 60583, 60596, 60597, 60598],
 [59067, 59068, 59069, 59082, 59083, ..., 60583, 60584, 60597, 60598, 60599],
 [59068, 59069, 59083, 59084, 60583, 60584, 60598, 60599]]
-----------------------------------------------------------------------------
type: 60600 * var * int64

or as a Numba-jittable CSR matrix from sigmaepsilon.math:

[6]:
mesh.nodal_adjacency(frmt="csr")
[6]:
60600x60600 CSR matrix of 1527274 values.

Pseudo Peripheral Nodes#

[7]:
from sigmaepsilon.math.topology.graph import pseudo_peripheral_nodes

csr = mesh.nodal_adjacency(frmt="csr")
ppn = pseudo_peripheral_nodes(csr)

Rooted Level Structure#

[8]:
from sigmaepsilon.math.topology.graph import rooted_level_structure

rls = rooted_level_structure(csr)

K-Nearest-Neighbours with Scipy or SkLearn#

[11]:
from sigmaepsilon.mesh import grid, PolyData, PointData
from sigmaepsilon.mesh.cells import H8

size = 80, 60, 20
shape = 10, 8, 4
coords, topo = grid(size=size, shape=shape, eshape="H8")
pd = PointData(coords=coords)
cd = H8(topo=topo)
mesh = PolyData(pd, cd)
mesh.k_nearest_cell_neighbours(k=3, knn_options=dict(max_distance=10.0))[:5]
[11]:
array([[0, 1, 4],
       [1, 2, 0],
       [2, 1, 3],
       [3, 2, 7],
       [4, 5, 0]], dtype=int64)