Skip to content

PointGroupAnalyzer reports incorrect point group for C2v molecules #4596

@bjmorgan

Description

@bjmorgan

Correction (2026-04-10): The 4-atom example below is actually D2d, not C2v — thanks to @newtontech for catching this in the linked PR. See this comment for a corrected 4-atom C2v example.

Python version

Python 3.12.3

Pymatgen version

2025.10.7

Operating system version

macOS (Darwin 24.6.0)

Current behavior

PointGroupAnalyzer misidentifies the point group for molecules with C2v symmetry.

For a 4-atom C2v molecule, it reports D2d at all tolerances tested (0.01, 0.1, 0.3).

For the 7-atom "Square-face capped trigonal prism" reference geometry from pymatgen's own chemenv module (AllCoordinationGeometries), results are tolerance-dependent:

  • tol=0.01: Cs (misses the sigma_h mirror plane)
  • tol=0.1: D2d (detects spurious symmetry)
  • tol=0.3: D2d (detects spurious symmetry)

The sigma_h mirror plane in the 7-atom case is exact to machine precision: applying the permutation [3,4,5,0,1,2,6] produces coordinates identical to negating the z-coordinates, with zero residual.

Expected Behavior

Both molecules should be identified as C2v at all reasonable tolerances.

Minimal example

import numpy as np
from pymatgen.core import Molecule
from pymatgen.symmetry.analyzer import PointGroupAnalyzer

# Case 1: 4-atom C2v molecule
# Two atoms paired in z, two on the mirror plane offset in y
mol = Molecule(["H"] * 4, [
    [0, 0, +1],
    [0, 0, -1],
    [+1, -1, 0],
    [-1, -1, 0],
])

for tol in [0.01, 0.1, 0.3]:
    pga = PointGroupAnalyzer(mol, tolerance=tol)
    print(f"tol={tol}: {pga.get_pointgroup()}")
# All report D2d; expected C2v

# Case 2: pymatgen's own chemenv reference geometry
from pymatgen.analysis.chemenv.coordination_environments.coordination_geometries import AllCoordinationGeometries

acg = AllCoordinationGeometries()
pts = acg.get_geometry_from_name('Square-face capped trigonal prism').points
mol2 = Molecule(["H"] * 7, pts)

for tol in [0.01, 0.1, 0.3]:
    pga = PointGroupAnalyzer(mol2, tolerance=tol)
    print(f"tol={tol}: {pga.get_pointgroup()}")
# tol=0.01: Cs, tol=0.1: D2d, tol=0.3: D2d
# Expected: C2v

Relevant files to reproduce this bug

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions