Source code for scgo.initialization.steric_scoring
"""Steric deficit scoring and blmin distance lookups for placement and GA."""
from __future__ import annotations
import numpy as np
from scipy.spatial.distance import pdist, squareform
def get_blmin_distance(
blmin: dict, atomic_number_a: int, atomic_number_b: int
) -> float:
"""Minimum allowed distance for an element pair from an ASE-style blmin table."""
key = (int(atomic_number_a), int(atomic_number_b))
if key in blmin:
return blmin[key]
return blmin[(int(atomic_number_b), int(atomic_number_a))]
[docs]
def steric_deficit(positions, atomic_numbers, blmin: dict) -> float:
"""Sum of blmin violations within a single structure (lower is better)."""
n_atoms = len(positions)
if n_atoms <= 1:
return 0.0
distances = squareform(pdist(positions))
deficit = 0.0
for i in range(n_atoms):
for j in range(i + 1, n_atoms):
required = get_blmin_distance(blmin, atomic_numbers[i], atomic_numbers[j])
gap = required - distances[i, j]
if gap > 0.0:
deficit += gap
return deficit
[docs]
def steric_deficit_two_sets(
left_positions,
left_numbers,
right_positions,
right_numbers,
blmin: dict,
) -> float:
"""Sum of blmin violations between two disjoint atom sets."""
deficit = 0.0
for i, left_pos in enumerate(left_positions):
for j, right_pos in enumerate(right_positions):
required = get_blmin_distance(blmin, left_numbers[i], right_numbers[j])
gap = required - np.linalg.norm(left_pos - right_pos)
if gap > 0.0:
deficit += gap
return deficit