4. Detect and List Empty Components
Why empty components accumulate
In a HyperMesh model that has passed through several rounds of geometry cleanup, remeshing, and part consolidation, components frequently survive their contents. A component is a container: it holds elements, geometry (surfaces, solids, lines), and references to properties and materials. When you delete elements or geometry during cleanup, the component itself is not removed. The result is a model browser cluttered with empty containers that inflate entity counts, confuse downstream reporting, and can silently break property or material assignment audits.
The task here is narrow and deliberate: detect components that contain no elements and no geometry, and emit a structured list for human review. This chapter does not delete anything. Deletion with safety checks is a separate concern; the value of this routine is that it produces a trustworthy, reviewable inventory first.
What "empty" means in HyperMesh terms
A component is empty when both of the following hold:
- It has zero elements. In the HyperMesh Python API, element counts are obtained per component via
hm_getentityvalueon theelemscollector, or by querying the element list associated with the component. - It has zero geometry. Geometry entities (surfaces, solids, lines, points) are attached to components through their collector membership, so the check must cover all geometry types, not just surfaces.
A component that holds only geometry but no elements is not empty by this definition — it may be a legitimate geometry-only container awaiting meshing. Likewise, a component with elements but no geometry is normal. Only the intersection of both conditions qualifies. This distinction matters because a naive element-count-only check will flag geometry-only components and produce false positives that erode trust in the report.
Query strategy and the API surface
The routine relies on a small set of stable HyperMesh Python calls. Component IDs are collected with hm_getentitylist or by iterating the component collector. For each component, counts are retrieved with hm_getentityvalue using the component ID and the appropriate entity type. Geometry counts require querying each geometry type separately because HyperMesh does not expose a single "all geometry" count per component.
The output is a structured list — one record per empty component — carrying the component ID, name, element count, geometry count, and a review status field. Writing this to a CSV or printing a formatted table gives reviewers something they can sort, annotate, and sign off on before any deletion step runs.
Implementation
The script below is self-contained. It assumes a model is loaded in the current HyperMesh session and that the hm and hmlib modules are importable, which is the standard environment when running a Python script from the HyperMesh command window or via hmbatch. It writes a CSV report and prints a summary line.
import csv
import hm
import hmlib
# Geometry entity types that can be attached to a component.
GEOM_TYPES = ("surfs", "solids", "lines", "points")
def get_component_ids():
"""Return all component IDs in the current model."""
return hm.getentitylist(hm.Component, 0)
def count_entities(comp_id, entity_type):
"""Return the number of entities of entity_type attached to comp_id."""
try:
return hm.getentityvalue(comp_id, entity_type, 0, 0)
except Exception:
# If a geometry type is absent from the model, treat as zero.
return 0
def classify_component(comp_id):
"""Return a dict describing the component's emptiness."""
n_elems = count_entities(comp_id, "elems")
n_geom = sum(count_entities(comp_id, g) for g in GEOM_TYPES)
name = hm.getentityvalue(comp_id, "name", 0, 0)
return {
"comp_id": comp_id,
"name": name,
"n_elems": n_elems,
"n_geom": n_geom,
"is_empty": (n_elems == 0 and n_geom == 0),
"review_status": "pending",
}
def detect_empty_components():
"""Return a list of records for all empty components."""
records = []
for cid in get_component_ids():
rec = classify_component(cid)
if rec["is_empty"]:
records.append(rec)
return records
def write_report(records, path="empty_components_review.csv"):
fields = ["comp_id", "name", "n_elems", "n_geom", "is_empty", "review_status"]
with open(path, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=fields)
writer.writeheader()
writer.writerows(records)
return path
if __name__ == "__main__":
empty = detect_empty_components()
out = write_report(empty)
print("Empty components found: %d" % len(empty))
print("Review file written to: %s" % out)
for r in empty:
print(" id=%s name=%s elems=%d geom=%d" %
(r["comp_id"], r["name"], r["n_elems"], r["n_geom"]))
Two implementation details deserve attention. First, count_entities wraps the query in a try/except because querying a geometry type that does not exist in the model can raise rather than return zero, depending on the HyperMesh version. Treating a failed geometry query as zero is safe here because the element count is checked independently. Second, the review_status field is initialized to "pending" so that the CSV is immediately usable as a sign-off sheet: a reviewer changes it to "approved" or "rejected" before the deletion step consumes it.
Running and verifying
Load a model that you know contains at least one empty component — for example, create a component, delete its elements, and leave the container in place. Run the script from the HyperMesh command window with execfile("detect_empty.py") or via hmbatch -python detect_empty.py. Expected observable behavior:
- The console prints
Empty components found: Nwhere N matches the number of containers you deliberately emptied. - The CSV contains one row per empty component with
n_elems=0andn_geom=0. - A geometry-only component you created as a control does not appear in the CSV, confirming the dual check works.
Common failure symptoms
| Symptom | Likely cause | Fix |
|---|---|---|
| All components flagged as empty | hm_getentityvalue argument order wrong for the installed version | Confirm the signature against the API help for your HyperMesh release; the entity type string must match exactly ("elems", not "elements") |
| Geometry-only components flagged | Only element count checked | Ensure the GEOM_TYPES sum is included in is_empty |
| Script raises on first geometry query | Geometry type absent from model | The try/except in count_entities handles this; verify it was not removed |
| CSV empty but model visibly has empty components | Components are children of an assembly and hold no direct entities | Decide policy: flag parents with no children, or skip parents entirely |
Review checklist before handoff
The deliverable of this chapter is the CSV, not a deletion. Before passing it to the deletion step, confirm: every row has n_elems=0 and n_geom=0; the control geometry-only component is absent; the review_status column is populated for each row; and the component names in the CSV match what the model browser shows, so reviewers can locate each entry without ambiguity. Only after these checks should the list be treated as an approved deletion candidate set.