Skip to content

Repository files navigation

Geonit

Physics-inspired geometry initialization for molecular and non-covalent optimization warm starts.

Geonit prepares chemically reasonable starting coordinates before a slower downstream optimizer, such as xTB, a force-field optimizer, or a quantum chemistry workflow, is allowed to spend real compute. It is designed for cases where the input geometry is usable enough to infer connectivity, but may contain stretched bonds, compressed angles, steric clashes, or fragile non-covalent contacts.

The central design choice is conservative: Geonit should make the smallest useful correction that improves optimizer readiness without moving the system into a different local minimum.

Repository:

https://github.com/Prasanna163/Geoinit.git

What Geonit Does

Geonit takes molecular coordinates, infers topology and chemically important structure classes, scores the geometry with a lightweight physical functional, and returns either relaxed coordinates or a selected warm-start candidate.

It is not a replacement for xTB, DFT, molecular dynamics, or a production force field. It is a pre-optimizer and selector for safer initial geometries.

Typical use cases:

  • Cleaning distorted XYZ geometries before xTB or DFT optimization.
  • Detecting basic geometry quality issues before running expensive jobs.
  • Comparing raw, UFF, guarded Geonit, and Geonit initialization paths.
  • Preparing non-covalent complexes while preserving fragment identity.
  • Running reproducible benchmark suites for geometry-initialization research.
  • Embedding geometry warm-start selection inside a larger Python pipeline.

Scientific Context

Geometry optimization often begins from structures that were drawn manually, retrieved from approximate coordinates, generated from templates, or composed by placing fragments near each other. These structures can contain local geometry errors that are small enough to look plausible but large enough to waste optimization steps or push an optimizer into a different basin.

Geonit targets this early stage. It emphasizes:

  • Bond-length sanity from covalent-radius rules.
  • Valence-angle consistency from coordination environments.
  • Clash removal without excessive global movement.
  • Rigid-fragment preservation for aromatic rings, carbonyls, amides, and linear multiple-bond fragments.
  • Non-covalent contact awareness for hydrogen-bond, polar, halogen, and pi-type interactions.
  • Raw-coordinate fallback when the selector cannot prove that a candidate is safe.

The important distinction is basin safety. UFF and similar initializers can produce larger step savings, but they may also move a distorted structure into a different local minimum. Geonit is built around avoiding that tradeoff.

Main Properties

Conservative Warm-Start Selection

Geonit generates a small portfolio of candidates, scores each candidate for chemical feasibility and movement from the original geometry, and selects a safe candidate only when it passes hard filters. Otherwise it falls back to the raw input coordinates.

Selection considers:

  • Chemical strain score.
  • Clash score.
  • Contact graph damage.
  • Class-specific risk score.
  • Raw-coordinate RMSD movement.
  • Fragment drift in complexes.
  • Estimated downstream xTB step benefit.

Physics-Inspired Functional

The scalar Geonit functional is a weighted sum of bonded, angular, steric, and dispersion-like terms:

E_total = w_bond * E_bond
        + w_angle * E_angle
        + w_clash * E_clash
        + w_disp * E_disp
        + w_coul * E_coul
        + w_rigid * E_rigid
        + w_anchor * E_anchor

Default weights are:

bond=10.0, angle=5.0, clash=1.0, disp=0.1, coul=0.0

Implemented terms include:

Term Purpose
Bond stretch Penalizes deviation from covalent-radius-based reference lengths.
Angle bend Penalizes deviation from coordination-based ideal angles.
Clash wall Penalizes compressed non-bonded contacts.
Dispersion Adds damped attractive non-bonded stabilization.
Rigid restraints Preserve detected rigid subgraphs and chemically fragile fragments.
Anchors Stabilize fragment/contact placement during candidate cleanup.

Chemical Class Awareness

Geonit detects structure classes that need extra care:

  • Linear multiple-bond chains such as CO2-like fragments.
  • Carbonyls and amides.
  • Aromatic rings and planar ring systems.
  • Rigid subgraphs that should not be distorted internally.
  • Multi-fragment non-covalent complexes.
  • Hydrogen-bond, polar, halogen, and pi-contact motifs.

These classes are used by guards, candidate generation, and selector rejection rules.

V1.0 Vectorized Compute Engine

Geonit V1.0 adds an opt-in vectorized energy/gradient engine. The same kernel can run on:

  • NumPy, always available and used as the safe CPU fallback.
  • PyTorch CPU, when PyTorch is installed.
  • CUDA, when PyTorch and a CUDA device are available.

The auto backend uses problem size to avoid paying GPU transfer overhead for small molecules.

Backend controls:

--engine scalar      # legacy scalar functional
--engine auto        # size-aware vectorized backend selection
--engine numpy       # force NumPy vectorized backend
--engine torch-cpu   # force PyTorch CPU backend if available
--engine cuda        # request CUDA, falling back safely if unavailable

Physics profile controls:

--profile v1         # frozen V1 behavior
--profile v2         # improved V2 physics

The V2 physics profile includes curvature-matched harmonic angle bending, bond-order-aware stiffness, and Becke-Johnson-style damped dispersion.

Benchmark-Backed Safety

The repository includes benchmark evidence packs for the V0.8 and V1.0 selectors. The benchmark suite contains 21 molecules and complexes with 10 distortions each, for 210 total trials.

Headline V0.8 result:

Geonit V0.8
xTB success:          210/210
same-minimum:         210/210
different-basin risk: 0/210
total steps:          6506 vs 6746 raw
accepted non-raw:     81/210

Headline V1.0 result:

Geonit V1.0
xTB success:          210/210
same-minimum:         210/210
different-basin risk: 0/210
total steps:          6506 vs 6746 raw
accepted non-raw:     139/210

Interpretation:

  • V1.0 preserves the V0.8 selector safety result.
  • V1.0 increases useful non-raw acceptance from 81 to 139 trials.
  • Complexes become warm-startable under the safe V1.0 selector path.
  • UFF has larger step savings in this suite, but much higher basin risk.

Evidence files live under:

benchmark_results_v0_8/
preliminary_results_v1_0/
project_tracking/

Installation

Development Install

git clone https://github.com/Prasanna163/Geoinit.git
cd Geoinit
python -m pip install -e .

The package requires Python 3.10 or newer.

Core dependencies:

numpy
scipy
pandas
matplotlib

Optional dependencies:

  • torch for PyTorch CPU or CUDA acceleration.
  • rdkit for UFF baseline benchmarking.
  • xtb executable on PATH for downstream xTB validation benchmarks.
  • joblib for parallel benchmark execution when --workers is not 1.

Install Directly From Git

python -m pip install git+https://github.com/Prasanna163/Geoinit.git

Build a Wheel

python -m pip install build wheel
python -m build

If you do not use build, the wheel can also be produced through pip:

python -m pip wheel . --no-deps -w dist

The package exposes the console command:

geonit

For compatibility with earlier scripts, geoinit is also installed as an alias. It can also be run as a module:

python -m geoinit --help

Command-Line Interface

Geonit currently exposes command-line entry points, not HTTP or FastAPI endpoints.

Top-level commands:

geonit relax
geonit report
geonit benchmark
geonit benchmark-xtb
geonit relax-complex

Relax a Distorted Geometry

Legacy scalar relaxation:

geonit relax examples\water_bad.xyz -o outputs\water_relaxed.xyz

Geonit V1.0:

geonit relax examples\water_bad.xyz --mode select -o outputs\water_select.xyz

Geonit V0.9 complex-candidate expansion:

geonit relax examples\complexes\water_dimer_bad.xyz --mode select-v0.9 -o outputs\water_dimer_v0_9.xyz

Geonit V1.0:

geonit relax examples\methanol_bad.xyz --mode select-v1.0 -o outputs\methanol_v1_0.xyz

Useful relaxation options:

--maxiter N
--sigma VALUE
--weights-bond VALUE
--weights-angle VALUE
--weights-clash VALUE
--weights-disp VALUE
--clash-mode exp|compact
--mode legacy|select|select-v0.9|select-v1.0

Generate a Geometry Report

geonit report examples\methanol_bad.xyz

The report prints:

  • Formula and atom count.
  • Detected bonds, angles, and non-bonded pairs.
  • Total Geonit energy and component breakdown.
  • Bond-error and clash diagnostics.
  • A detailed bond table.
  • Highest angle deviations.

Run the Geometric Benchmark Suite

geonit benchmark --suite medium --out outputs\geoinit_geometric_summary.csv

Suites:

small
medium

Run the xTB Validation Benchmark

The xTB benchmark shells out to the xtb executable and compares raw, UFF, guarded Geonit, and Geonit initialization paths.

geonit benchmark-xtb --suite medium --distortions 10 --baselines raw uff geoinit_guarded geoinit_select --out preliminary_results_v1_0\geoinit_v1_0_casewise_results.csv

V1.0 selector benchmark:

geonit benchmark-xtb --suite medium --distortions 10 `
  --baselines raw uff geoinit_guarded geoinit_select `
  --select-version v1_0 `
  --engine auto `
  --profile v2 `
  --workers -1 `
  --out preliminary_results_v1_0\geoinit_v1_0_casewise_results.csv

Important benchmark options:

--suite small|medium
--distortions N
--baselines raw uff geoinit_guarded geoinit_select
--select-version v0_8|v0_9|v1_0
--engine scalar|auto|numpy|torch-cpu|cuda
--profile v1|v2
--workers N
--charge INT
--uhf INT
--xtb-method gfn0|gfn1|gfn2

Relax a Host-Guest Complex

geonit relax-complex examples\dmf_bad.xyz examples\water_bad.xyz -o outputs\dmf_water_relaxed.xyz

This command reads host and guest XYZ files, stacks them into one complex, and applies the complex-aware relaxation path.

Python Integration

Geonit can be used as a normal Python module inside scripts, notebooks, workflow managers, or backend services.

Load and Save XYZ Files

from geoinit.core.atoms import Molecule

mol = Molecule.from_xyz("examples/water_bad.xyz")
print(mol.symbols)
print(mol.coords)

mol.to_xyz("outputs/copy.xyz", comment="Copied by Geonit")

Infer Topology

from geoinit.core.atoms import Molecule
from geoinit.core.topology import Topology

mol = Molecule.from_xyz("examples/methanol_bad.xyz")
topology = Topology(mol.symbols, mol.coords)

print(topology.bonds)
print(topology.angles)
print(topology.nonbonded_pairs)

Run Legacy Relaxation

from geoinit.core.atoms import Molecule
from geoinit.optimize.relax import relax

mol = Molecule.from_xyz("examples/water_bad.xyz")
result = relax(mol.symbols, mol.coords, maxiter=500)

print(result.success)
print(result.n_steps)
print(result.final_energy)

Select a Warm-Start Candidate

from geoinit.core.atoms import Molecule
from geoinit.optimize.selector import select_initial_geometry

mol = Molecule.from_xyz("examples/water_bad.xyz")
selection = select_initial_geometry(mol.symbols, mol.coords)

print(selection.selected_name)
print(selection.accepted)
coords_for_xtb = selection.selected_coords

Use the V0.9 Policy

from geoinit.core.atoms import Molecule
from geoinit.optimize.selector import select_initial_geometry, v0_9_selection_policy

mol = Molecule.from_xyz("examples/complexes/water_dimer_bad.xyz")
selection = select_initial_geometry(
    mol.symbols,
    mol.coords,
    policy=v0_9_selection_policy(),
)

Use the V1.0 Policy

from geoinit.core.atoms import Molecule
from geoinit.optimize.selector import select_initial_geometry, v1_0_selection_policy

mol = Molecule.from_xyz("examples/complexes/benzene_co2_bad.xyz")
selection = select_initial_geometry(
    mol.symbols,
    mol.coords,
    policy=v1_0_selection_policy(),
)

Force the Vectorized Engine

from geoinit.core.atoms import Molecule
from geoinit.optimize.relax import relax

mol = Molecule.from_xyz("examples/methanol_bad.xyz")
result = relax(
    mol.symbols,
    mol.coords,
    engine="auto",
    profile="v2",
)

Integration Patterns

As a Pre-Optimization Step

Use Geonit before launching xTB or another downstream optimizer:

from pathlib import Path

from geoinit.core.atoms import Molecule
from geoinit.core.io_xyz import write_xyz
from geoinit.optimize.selector import select_initial_geometry, v1_0_selection_policy

def prepare_for_xtb(input_xyz: str, output_xyz: str) -> str:
    mol = Molecule.from_xyz(input_xyz)
    selection = select_initial_geometry(
        mol.symbols,
        mol.coords,
        policy=v1_0_selection_policy(),
    )
    write_xyz(
        output_xyz,
        mol.symbols,
        selection.selected_coords,
        comment=f"Geonit selected={selection.selected_name} accepted={selection.accepted}",
    )
    return output_xyz

prepared = prepare_for_xtb("input.xyz", "prepared.xyz")

Then call your downstream optimizer on prepared.xyz.

From a Larger Python Pipeline

The safest integration contract is:

  1. Keep the original raw coordinates.
  2. Run Geonit selection.
  3. Record selected_name, accepted, fallback_reason, and policy version.
  4. Use selected_coords for downstream optimization.
  5. Compare final downstream energy against raw when validating a new chemistry class.

Minimal result metadata:

metadata = {
    "selector_version": selection.policy.selector_version,
    "selected_name": selection.selected_name,
    "accepted": selection.accepted,
    "fallback_reason": selection.fallback_reason,
    "candidate_count": len(selection.candidates),
}

From a Backend or Web Service

The repository does not currently define REST endpoints. To expose Geonit through an API, wrap the Python API rather than shelling out unless you need strict process isolation.

Example FastAPI-style wrapper:

from fastapi import FastAPI
from pydantic import BaseModel

from geoinit.optimize.selector import select_initial_geometry, v1_0_selection_policy

app = FastAPI()

class GeometryRequest(BaseModel):
    symbols: list[str]
    coords: list[list[float]]

@app.post("/api/geonit/select-v1.0")
def select_v1_geometry(req: GeometryRequest):
    selection = select_initial_geometry(
        req.symbols,
        req.coords,
        policy=v1_0_selection_policy(),
    )
    return {
        "selected_name": selection.selected_name,
        "accepted": selection.accepted,
        "fallback_reason": selection.fallback_reason,
        "coords": selection.selected_coords.tolist(),
    }

Suggested service endpoints if you build a backend:

GET  /api/health
POST /api/geonit/report
POST /api/geonit/relax
POST /api/geonit/select
POST /api/geonit/select-v1.0

From the Command Line in Another Tool

If another application invokes Geonit as a subprocess, use python -m geoinit for interpreter consistency:

python -m geoinit relax input.xyz --mode select-v1.0 -o prepared.xyz

This avoids ambiguity when multiple Python environments are installed.

Repository Layout

Geonit/
|-- pyproject.toml
|-- README.md
|-- Geonit/
|   |-- __init__.py
|   |-- __main__.py
|   |-- cli/
|   |   `-- main.py
|   |-- core/
|   |   |-- atoms.py
|   |   |-- bond_rules.py
|   |   |-- classes.py
|   |   |-- constraints.py
|   |   |-- contact_graph.py
|   |   |-- geometry.py
|   |   |-- io_xyz.py
|   |   |-- params.py
|   |   `-- topology.py
|   |-- energy/
|   |   |-- angle.py
|   |   |-- bond.py
|   |   |-- engine.py
|   |   |-- functional.py
|   |   `-- nonbonded.py
|   |-- compute/
|   |   `-- backends.py
|   |-- optimize/
|   |   |-- candidates.py
|   |   |-- complex.py
|   |   |-- guards.py
|   |   |-- project.py
|   |   |-- relax.py
|   |   `-- selector.py
|   |-- benchmark/
|   |   |-- distortion.py
|   |   |-- metrics.py
|   |   |-- plot_benchmark.py
|   |   |-- select_report.py
|   |   |-- suite.py
|   |   |-- uff_runner.py
|   |   `-- xtb_runner.py
|   `-- calibration/
|       `-- class_stats.py
|-- examples/
|-- tests/
|-- benchmark_results_v0_8/
|-- benchmark_results_v0_9/
|-- preliminary_results_v1_0/
`-- project_tracking/

Packaging Notes

pyproject.toml defines the package name and console script:

[project]
name = "geonit"

[project.scripts]
geonit = "geoinit.cli.main:main"
geoinit = "geoinit.cli.main:main"

The distribution is named geonit, while the import package remains geoinit for backward compatibility. Package discovery is explicitly restricted to geoinit*, so benchmark outputs, tracking files, examples, and tests are not accidentally included as importable packages in the wheel.

[tool.setuptools.packages.find]
include = ["geoinit*"]

Recommended release workflow:

python -m pytest
python -m build
python -m twine check dist\*

For a private/internal install:

python -m pip install dist\geonit-1.0.0-py3-none-any.whl

Testing

Run the unit test suite:

python -m pytest

Current local verification for this checkout:

52 passed

The xTB benchmarks require the external xtb executable and are intentionally separate from the fast unit test suite.

Benchmark Artifacts

Important generated artifacts:

benchmark_results_v0_8/geoinit_v0_8_casewise_results.csv
benchmark_results_v0_8/FINAL_RESULTS.md
preliminary_results_v1_0/geoinit_v1_0_casewise_results.csv
preliminary_results_v1_0/geoinit_v1_0_benchmark_summary.csv
preliminary_results_v1_0/geoinit_v1_0_candidate_rows.csv
preliminary_results_v1_0/geoinit_v1_0_candidate_class_summary.csv
preliminary_results_v1_0/compare_v0_8_vs_v1_0.py

Use the casewise CSVs for per-trial inspection and the candidate files to understand why a selector accepted or rejected a candidate.

Design Philosophy

Geonit is intentionally cautious.

The goal is not to maximize apparent step savings on every distorted input. The goal is to provide a useful warm start when that warm start can be justified, and to fall back to the raw geometry when safety is uncertain.

That philosophy is why the benchmark tables track same-minimum rate and different-basin risk, not only convergence speed.

Current Limitations

  • Input support is currently centered on XYZ coordinates.
  • The built-in topology inference is geometry/radius based and can be confused by severely pathological structures.
  • xTB validation requires an external xtb installation.
  • UFF baseline comparison requires RDKit.
  • The repository exposes a CLI and Python API, not a built-in web service.
  • Licensing metadata and a standalone LICENSE file should be added before a formal public release if redistribution terms need to be explicit.

Citation / Project Description

Short description:

Geonit is a physics-inspired molecular geometry initializer that generates
basin-safe warm-start coordinates for downstream optimization workflows.

Long description:

Geonit combines radius-based topology inference, chemical-class detection,
lightweight energy scoring, guarded relaxation, and conservative candidate
selection to prepare molecular and non-covalent complex geometries before
expensive downstream optimization. Its selector-first workflow is benchmarked
against raw xTB and UFF baselines with emphasis on same-minimum preservation and
different-basin risk.

About

Basin-safe molecular geometry initializer for accelerating xTB convergence with physics-guided, GPU-ready warm starts.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages