Table of Contents

August 20, 2026 · View on GitHub

  1. About
    1. Features
    2. Migrate onto CON
    3. Install
    4. Tutorial
    5. Design Decisions
      1. FFI Layer
    6. Specification
      1. CON format
      2. convel format
    7. Capabilities
    8. Citation
  2. License

About

readcon-core is the reference implementation of versioned .con / .convel. Rare-event codes already checkpoint on CON. This library is the spec and the hourglass API so the rest of the atomistic stack reads the same file: optimizers, potential drivers, analysis tools, campaign stores, and ML hand-off.

One frame is complete: cell, type-grouped coordinates, per-direction fixed masks, column-5 atom_id, optional per-atom sections (velocities, forces, energies, charges, spins, magmoms), and JSON metadata (spec v2-v3, docs/orgmode/spec.org). Saddle, dimer, and NEB codes already depend on that payload.

Layer Role
Spec + hot path Spec v3 parse/write, validate, units, sections, SoA, Cachegrind CI
Hourglass ABI C / C++ / Python / Julia / Fortran (rkr_*): link CON into any language
Device / ML hand-off DLPack (optional CUDA); optional metatensor TensorBlock without leaving CON authority
Ingress Chemfiles import/selection: foreign structures into CON
Campaigns index_proj + readcon-db (cargo add / pip install; docs · docs.rs)

Already on that path: rare-event clients, rgpot, rgpycrumbs, ASE adapters, amsel, campaign stores, and anything that takes DLPack or metatensor blocks.

Rust rewrite of readCon. Chemfiles owns format diversity at the edge; this crate owns CON fidelity on the wire and in memory.

Measurements: Cachegrind I-refs (examples/cachegrind_harness.rs); Python ASV + spyglass on PRs (benchmarks/); CON peers via benches/compare_readers.py (and other scripts under benches/). See docs/orgmode/benchmarks.org.

Features

  • CON and convel: Coordinates; optional sections declared in sections (velocities, forces, energies, charges, spins, magmoms). Velocities also auto-detect on legacy .convel without a sections key.
  • Lazy iteration: ConFrameIterator; next_with_raw_span keeps the on-disk blob for corpus ingest.
  • Hot path: fast-float2, memmap2, Cachegrind-tracked scenarios.
  • Parallel frames: Rayon behind the parallel Cargo feature.
  • Bindings: Python (PyO3), Julia (ccall), C (shipped header), C++ (RAII header), Fortran (fpm); hourglass ABI patterned on metatensor.
  • Metadata helpers: Typed energy, frame_index, time, timestep, neb_bead, neb_band across bindings; raw JSON still available.
  • Validation: validate=true enforces finiteness, reserved keys, geometry, labels, symbols, section presence, identity columns.
  • Fidelity: atom_id, per-direction fixed masks, and declared optional sections round-trip through the core reader/writer.
  • Campaigns: Pair with readcon-db (CON-text indexes, dedup, multi-reader; docs · docs.rs).
  • RPC: Cap'n Proto behind the rpc feature.

Migrate onto CON

Why switch: use a real frame API and multi-language library instead of hand-rolling XYZ and a private atoms object.

How-to: docs/orgmode/migrate.org. Chemfiles path (CI-run): chemfiles-notebook. Campaigns: readcon-db docs · docs.rs/readcon-db. Plotting: chemparseplot.

Install

Language Install Destination
Rust cargo add readcon-core docs.rs
Python pip install readcon PyPI
Python + chemfiles pip install readcon-chemfiles PyPI
Campaign store cargo add readcon-db / pip install readcon-db docs · docs.rs
Julia julia --project=julia/ReadCon -e 'using Pkg; Pkg.instantiate()' bindings
C / C++ CMake FetchContent / find_package(readcon-core) (cxx tarball) headers + libreadcon_core + readcon-core.pc
C / C++ Meson dependency('readcon-core') (wrapdb / wrap-file) same
C / C++ cargo-c cargo cinstall --release --prefix /usr/local same

The C/C++ headers are shipped (include/readcon-core.h). cbindgen is a maintainer tool, not a consumer dependency. C99 (readcon-core.h) or C++17 (readcon-core.hpp) compiler. FetchContent URL: readcon-core-cxx-$VERSION.tar.gz on the GitHub Release. Full matrix: getting-started.

Tutorial

Install, read a multi-frame fixture, inspect atom_id, write a round-trip, build a frame with energy. Full steps: docs/orgmode/tutorial.org (or the published HTML tutorial page).

Short Python path from the repository root:

import readcon

for frame in readcon.iter_con("resources/test/tiny_multi_cuh2.con"):
    print(frame.cell, len(frame), frame.energy)

frames = readcon.read_con("resources/test/tiny_multi_cuh2.con")
readcon.write_con("out.con", frames)

atoms = [readcon.Atom("Cu", 0.0, 0.0, 0.0, atom_id=0, mass=63.546)]
frame = readcon.ConFrame(cell=[10.0, 10.0, 10.0], angles=[90.0, 90.0, 90.0], atoms=atoms)
frame.set_energy(-42.5)
frame.write_con("built.con")

Rust smoke (same fixture):

cargo run --example rust_usage -- resources/test/tiny_multi_cuh2.con

Other languages and task recipes: docs/orgmode/howto.org. Conversion from XYZ/PDB/GRO: chemfiles-tutorial.

Design Decisions

  • Lazy parsing: ConFrameIterator parses one frame at a time for large trajectories.
  • Hourglass FFI: shipped C header plus a hand-written C++ RAII wrapper, same pattern as metatensor. CMake FetchContent, Meson wrap, and readcon-core.pc do not run cbindgen.

FFI Layer

Two exposure modes:

  1. Opaque handles (RKRConFrame*): client calls Rust accessors (rkr_frame_get_header_line, …). Hides layout; ABI can evolve behind the handle.
  2. Transparent #[repr(C)] extract (rkr_frame_to_c_frameCFrame): client owns a flat atom table for hot loops and frees it with free_c_frame.

Specification

See docs/orgmode/spec.org (or the published HTML build) for the full specification. A summary follows.

CON format

  • A 9-line header (comments, cell dimensions, cell angles, atom type/count/mass metadata)
  • Line 2 is reserved for spec-v2 JSON metadata
  • Per-type coordinate blocks (symbol, label, atom lines with x y z fixed atomID)
  • Optional spec-v2 sections and validate metadata for declared per-atom sections and strict validation
  • Multiple frames are concatenated directly with no separator

convel format

Same as CON, with an additional velocity section after each frame's coordinates:

  • A blank separator line
  • Per-type velocity blocks (symbol, label, atom lines with vx vy vz fixed atomID)

Capabilities

Area Surface
Payload Constraints, atom_id; optional velocities / forces / energies / charges / spins / magmoms; versioned JSON
Languages One rkr_* surface for Fortran / C / C++ / Python / Julia
Spec v2-v3, validate=true, declared sections (including optional physics blocks above), units (v3)
Tensors DLPack; optional metatensor TensorBlock
Campaigns index_proj + readcon-db (docs · docs.rs)
Import Optional chemfiles → CON
Measurements Cachegrind I-refs; PR ASV + spyglass; benches/compare_readers.py

Predecessor: readCon.

Citation

If you use readcon-core in academic work, please cite it via the metadata in CITATION.cff. A Zenodo DOI is minted on a freeze tag and recorded in CITATION.cff identifiers; this tree does not invent one.

License

MIT.