# Table of Contents
1. [About](#orgd6d7168)
1. [Features](#org6d404b0)
2. [Migrate onto CON](#orgd595133)
3. [Install](#org65e1283)
4. [Tutorial](#orgdf221ce)
5. [Design Decisions](#org297db41)
1. [FFI Layer](#org5b8d30e)
6. [Specification](#orgd94c691)
1. [CON format](#org8295504)
2. [convel format](#orgc9210ef)
7. [Capabilities](#org82593f8)
8. [Citation](#org7bc2aad)
2. [License](#orgd83f4c1)
<a id="orgd6d7168"></a>
# About
`readcon-core` is the reference implementation of versioned `.con` / `.convel`.
This stack **puts CON everywhere**: every optimizer, potential driver, analysis
tool, campaign store, and ML hand-off that needs a durable atomic configuration
with constraints, forces, and identity.
CON is human-readable and complete on one frame: 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](docs/orgmode/spec.org)).
That payload is why saddle, dimer, and NEB codes already work on CON; the
library exists so the rest of the atomistic stack adopts the same file.
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
<colgroup>
<col class="org-left" />
<col class="org-left" />
</colgroup>
<thead>
<tr>
<th scope="col" class="org-left">Layer</th>
<th scope="col" class="org-left">Role in spreading CON</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-left">Spec + hot path</td>
<td class="org-left">Spec v3 parse/write, <code>validate</code>, units, <code>sections</code>, SoA, Cachegrind CI</td>
</tr>
<tr>
<td class="org-left">Hourglass ABI</td>
<td class="org-left">C / C++ / Python / Julia / Fortran (<code>rkr_*</code>): link CON into any language</td>
</tr>
<tr>
<td class="org-left">Device / ML hand-off</td>
<td class="org-left">DLPack (optional CUDA); optional metatensor <code>TensorBlock</code> without leaving CON authority</td>
</tr>
<tr>
<td class="org-left">Ingress</td>
<td class="org-left">Chemfiles import/selection: foreign structures <b>into</b> CON</td>
</tr>
<tr>
<td class="org-left">Campaigns</td>
<td class="org-left"><code>index_proj</code> + <a href="https://github.com/lode-org/readcon-db">readcon-db</a> (<code>cargo add</code> / <code>pip install</code>; <a href="https://lode-org.github.io/readcon-db/">docs</a> · <a href="https://docs.rs/readcon-db">docs.rs</a>)</td>
</tr>
</tbody>
</table>
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](https://github.com/HaoZeke/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](docs/orgmode/benchmarks.org).
<a id="org6d404b0"></a>
## 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](https://github.com/aldanor/fast-float-rust), [memmap2](https://docs.rs/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](https://github.com/metatensor/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](https://github.com/lode-org/readcon-db) (CON-text indexes, dedup, multi-reader; [docs](https://lode-org.github.io/readcon-db/) · [docs.rs](https://docs.rs/readcon-db)).
- **RPC:** Cap'n Proto behind the `rpc` feature.
<a id="orgd595133"></a>
## Migrate onto CON
Why switch: use a real frame API and multi-language library instead of
hand-rolling XYZ and a private atoms object.
- **API:** parse/write, builders, metadata, validation, compression, lazy multi-frame iteration
- **Payload:** constraints, `atom_id`, optional sections, versioned JSON on one frame
- **Selection:** `select_atoms` / `rkr_frame_select` (`name H`, bonds/angles when topology is present)
- **Languages:** hourglass `rkr_*` in Fortran / C / C++ / Python / Julia / Rust (same semantics when you add a language)
- **Campaigns:** [readcon-db](https://github.com/lode-org/readcon-db) on CON text (energy / formula / sections, dedup, multi-reader; [docs](https://lode-org.github.io/readcon-db/) · [docs.rs](https://docs.rs/readcon-db))
- **Plotting:** [chemparseplot](https://chemparseplot.rgoswami.me) (+ [rgpycrumbs](https://rgpycrumbs.rgoswami.me)) on the same files
- **Measurements:** Cachegrind I-refs; PR ASV + spyglass; peer scripts in `benches/` — [benchmarks.org](docs/orgmode/benchmarks.org)
# foreign → CON (needs --features chemfiles)
cargo run --release --features chemfiles -- convert structure.xyz structure.con
# Python (readcon-chemfiles or maturin --features python,chemfiles)
# python -c "import readcon; readcon.convert_to_con('structure.xyz','structure.con')"
How-to: [docs/orgmode/migrate.org](docs/orgmode/migrate.org). Chemfiles path (CI-run):
[chemfiles-notebook](docs/orgmode/chemfiles-notebook.org). Campaigns:
[readcon-db docs](https://lode-org.github.io/readcon-db/) ·
[docs.rs/readcon-db](https://docs.rs/readcon-db). Plotting:
[chemparseplot](https://chemparseplot.rgoswami.me).
<a id="org65e1283"></a>
## Install
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
<colgroup>
<col class="org-left" />
<col class="org-left" />
<col class="org-left" />
</colgroup>
<thead>
<tr>
<th scope="col" class="org-left">Language</th>
<th scope="col" class="org-left">Install</th>
<th scope="col" class="org-left">Destination</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-left">Rust</td>
<td class="org-left"><code>cargo add readcon-core</code></td>
<td class="org-left"><a href="https://docs.rs/readcon-core">docs.rs</a></td>
</tr>
<tr>
<td class="org-left">Python</td>
<td class="org-left"><code>pip install readcon</code></td>
<td class="org-left"><a href="https://pypi.org/project/readcon/">PyPI</a></td>
</tr>
<tr>
<td class="org-left">Python + chemfiles</td>
<td class="org-left"><code>pip install readcon-chemfiles</code></td>
<td class="org-left"><a href="https://pypi.org/project/readcon-chemfiles/">PyPI</a></td>
</tr>
<tr>
<td class="org-left">Campaign store</td>
<td class="org-left"><code>cargo add readcon-db</code> / <code>pip install readcon-db</code></td>
<td class="org-left"><a href="https://lode-org.github.io/readcon-db/">docs</a> · <a href="https://docs.rs/readcon-db">docs.rs</a></td>
</tr>
<tr>
<td class="org-left">Julia</td>
<td class="org-left"><code>julia --project=julia/ReadCon -e 'using Pkg; Pkg.instantiate()'</code></td>
<td class="org-left"><a href="docs/orgmode/bindings.html">bindings</a></td>
</tr>
<tr>
<td class="org-left">C / C++ CMake</td>
<td class="org-left"><code>FetchContent</code> / <code>find_package(readcon-core)</code> (cxx tarball)</td>
<td class="org-left">headers + <code>libreadcon_core</code> + <code>readcon-core.pc</code></td>
</tr>
<tr>
<td class="org-left">C / C++ Meson</td>
<td class="org-left"><code>dependency('readcon-core')</code> (wrapdb / wrap-file)</td>
<td class="org-left">same</td>
</tr>
<tr>
<td class="org-left">C / C++ cargo-c</td>
<td class="org-left"><code>cargo cinstall --release --prefix /usr/local</code></td>
<td class="org-left">same</td>
</tr>
</tbody>
</table>
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](docs/orgmode/getting-started.org).
<a id="orgdf221ce"></a>
## Tutorial
One Good Tutorial (Diátaxis): install, read a multi-frame fixture, inspect
`atom_id`, write a round-trip, build a frame with energy. Full steps:
[docs/orgmode/tutorial.org](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](docs/orgmode/howto.org).
Conversion from XYZ/PDB/GRO: [chemfiles-tutorial](docs/orgmode/chemfiles-tutorial.org).
<a id="org297db41"></a>
## 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](https://github.com/metatensor/metatensor). CMake FetchContent, Meson wrap, and `readcon-core.pc` do not run cbindgen.
<a id="org5b8d30e"></a>
### 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_frame` → `CFrame`):
client owns a flat atom table for hot loops and frees it with
`free_c_frame`.
<a id="orgd94c691"></a>
## Specification
See [docs/orgmode/spec.org](docs/orgmode/spec.org) (or the [published HTML build](https://lode-org.github.io/readcon-core/spec.html)) for the full specification. A summary follows.
<a id="org8295504"></a>
### 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
<a id="orgc9210ef"></a>
### 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)
<a id="org82593f8"></a>
## Capabilities
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
<colgroup>
<col class="org-left" />
<col class="org-left" />
</colgroup>
<thead>
<tr>
<th scope="col" class="org-left">Area</th>
<th scope="col" class="org-left">Surface</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-left">Payload</td>
<td class="org-left">Constraints, <code>atom_id</code>; optional velocities / forces / energies / charges / spins / magmoms; versioned JSON</td>
</tr>
<tr>
<td class="org-left">Languages</td>
<td class="org-left">One <code>rkr_*</code> surface for Fortran / C / C++ / Python / Julia</td>
</tr>
<tr>
<td class="org-left">Spec</td>
<td class="org-left">v2–v3, <code>validate=true</code>, declared sections (including optional physics blocks above), units (v3)</td>
</tr>
<tr>
<td class="org-left">Tensors</td>
<td class="org-left">DLPack; optional metatensor <code>TensorBlock</code></td>
</tr>
<tr>
<td class="org-left">Campaigns</td>
<td class="org-left"><code>index_proj</code> + <a href="https://github.com/lode-org/readcon-db">readcon-db</a> (<a href="https://lode-org.github.io/readcon-db/">docs</a> · <a href="https://docs.rs/readcon-db">docs.rs</a>)</td>
</tr>
<tr>
<td class="org-left">Import</td>
<td class="org-left">Optional chemfiles → CON</td>
</tr>
<tr>
<td class="org-left">Measurements</td>
<td class="org-left">Cachegrind I-refs; PR ASV + spyglass; <code>benches/compare_readers.py</code></td>
</tr>
</tbody>
</table>
Predecessor: [readCon](https://github.com/HaoZeke/readCon).
<a id="org7bc2aad"></a>
## Citation
If you use `readcon-core` in academic work, please cite it via the metadata in [CITATION.cff](CITATION.cff). The Zenodo DOI tracks the latest release.
<a id="orgd83f4c1"></a>
# License
MIT.