Skip to content

Node Indexing

HOMER supports two ways to reference nodes in a MeshElement: by integer index (position in the node list) or by user-assigned ID. Understanding the difference is important when building complex multi-element meshes.


Index-Based Nodes (Default)

By default, MeshElement uses integer indices into the parent Mesh's nodes list:

from HOMER import Mesh, MeshNode, MeshElement, H3Basis
import numpy as np

node0 = MeshNode(loc=[0., 0., 0.], du=np.zeros(3), dv=np.zeros(3), dudv=np.zeros(3))
node1 = MeshNode(loc=[1., 0., 0.], du=np.zeros(3), dv=np.zeros(3), dudv=np.zeros(3))
node2 = MeshNode(loc=[0., 1., 0.], du=np.zeros(3), dv=np.zeros(3), dudv=np.zeros(3))
node3 = MeshNode(loc=[1., 1., 0.], du=np.zeros(3), dv=np.zeros(3), dudv=np.zeros(3))

# Indices 0, 1, 2, 3 refer to positions in [node0, node1, node2, node3]
element = MeshElement(
    node_indexes=[0, 1, 2, 3],
    basis_functions=(H3Basis, H3Basis),
)
mesh = Mesh(nodes=[node0, node1, node2, node3], elements=element)

ID-Based Nodes

Assign a string or integer id to nodes and reference them by ID in elements:

node0 = MeshNode(loc=[0., 0., 0.], id='corner_00',
                 du=np.zeros(3), dv=np.zeros(3), dudv=np.zeros(3))
node1 = MeshNode(loc=[1., 0., 0.], id='corner_10',
                 du=np.zeros(3), dv=np.zeros(3), dudv=np.zeros(3))
node2 = MeshNode(loc=[0., 1., 0.], id='corner_01',
                 du=np.zeros(3), dv=np.zeros(3), dudv=np.zeros(3))
node3 = MeshNode(loc=[1., 1., 0.], id='corner_11',
                 du=np.zeros(3), dv=np.zeros(3), dudv=np.zeros(3))

# Reference by ID instead of index
element = MeshElement(
    node_ids=['corner_00', 'corner_10', 'corner_01', 'corner_11'],
    basis_functions=(H3Basis, H3Basis),
)
mesh = Mesh(nodes=[node0, node1, node2, node3], elements=element)

Shared Nodes Across Elements

For multi-element meshes, neighbouring elements share boundary nodes. Index- based referencing makes this straightforward because the same integer refers to the same node object:

# Two adjacent H3 elements sharing nodes 1 and 3
#  0 - 1 - 4
#  |   |   |
#  2 - 3 - 5

all_nodes = [
    MeshNode(loc=[0.,0.,0.], du=np.zeros(3), dv=np.zeros(3), dudv=np.zeros(3)),  # 0
    MeshNode(loc=[1.,0.,0.], du=np.zeros(3), dv=np.zeros(3), dudv=np.zeros(3)),  # 1 – shared
    MeshNode(loc=[0.,1.,0.], du=np.zeros(3), dv=np.zeros(3), dudv=np.zeros(3)),  # 2
    MeshNode(loc=[1.,1.,0.], du=np.zeros(3), dv=np.zeros(3), dudv=np.zeros(3)),  # 3 – shared
    MeshNode(loc=[2.,0.,0.], du=np.zeros(3), dv=np.zeros(3), dudv=np.zeros(3)),  # 4
    MeshNode(loc=[2.,1.,0.], du=np.zeros(3), dv=np.zeros(3), dudv=np.zeros(3)),  # 5
]

elem_left  = MeshElement(node_indexes=[0,1,2,3], basis_functions=(H3Basis, H3Basis))
elem_right = MeshElement(node_indexes=[1,4,3,5], basis_functions=(H3Basis, H3Basis))

mesh = Mesh(nodes=all_nodes, elements=[elem_left, elem_right])

Looking Up Nodes and Elements by ID

When IDs are set, you can retrieve objects by ID:

# Get a node by ID
node = mesh.get_node('corner_00')

# Get an element by ID
elem = mesh.get_element('my_elem_id')

Node Ordering Within an Element

The order of nodes in node_indexes follows Fortran (column-major) order for the tensor product: the first index varies fastest.

For a 2-D element with basis order [u_basis, v_basis]:

node_indexes = [  # xi_u × xi_v grid
    node(u=0, v=0),   # index 0
    node(u=1, v=0),   # index 1
    node(u=0, v=1),   # index 2
    node(u=1, v=1),   # index 3
]

For a 3-D element, the order is u fastest, then v, then w.