# DREID-Forge
**DREID-Forge** is a high-performance, pure-Rust library for automated DREIDING force field parameterization. It orchestrates atom typing, partial charge calculation, and potential energy function generation to produce simulation-ready inputs for both biological macromolecules and arbitrary chemical systems—all without leaving the Rust type system.
## Highlights
- **Automated atom typing** — assigns DREIDING atom types (e.g., `C_3`, `O_R`, `N_2`) based on element, hybridization, and local bonding environment via the `dreid-typer` crate.
- **Flexible charge assignment** — supports global QEq charge equilibration via `cheq`, or hybrid mode combining classical force field charges for biomolecules (AMBER/CHARMM) with QEq for ligands via `ffcharge`.
- **Embedded QEq for ligands** — polarizes ligand charges based on the surrounding protein electrostatic environment using efficient spatial indexing.
- **Comprehensive potential generation** — produces bond (harmonic/Morse), angle (cosine/theta-harmonic), torsion, inversion, van der Waals (LJ 12-6/Buckingham), and hydrogen bond potentials.
- **Format interoperability** — reads PDB, mmCIF, MOL2, and SDF structures with optional biomolecular preparation (cleaning, protonation, solvation); exports to BGF format.
- **Rust-first ergonomics** — no FFI, no global mutable state, edition 2024, and a carefully designed public API with comprehensive RustDoc documentation.
## Parameterization Pipeline at a Glance
```mermaid
flowchart LR
Input[System] --> Intermediate[IntermediateSystem]
Intermediate --> Typer[Atom Typing]
Typer --> Charge[Charge Calculation]
Charge --> ParamGen[Parameter Generation]
ParamGen --> Output[ForgedSystem]
```
1. **Convert** — `IntermediateSystem::from_system` builds neighbor lists and prepares bonds for physical order assignment.
2. **Type** — `assign_atom_types` delegates to `dreid-typer` to assign DREIDING atom types and enumerate angles, torsions, and inversions.
3. **Charge** — `assign_charges` computes partial charges using QEq (global or embedded) or classical force field parameters.
4. **Generate** — `generate_parameters` produces all bonded and non-bonded potential parameters according to DREIDING rules.
5. **Output** — The resulting `ForgedSystem` is ready for export to BGF format.
## Quick Start
### For CLI Users
Install the latest DREID-Forge CLI binary from the [releases page](https://github.com/caltechmsc/dreid-forge/releases) or via `cargo`:
```bash
cargo install dreid-forge
```
Once the `dforge` binary is installed, you can parameterize a molecule in a single step:
```bash
dforge bio -i input.pdb -o output.bgf
```
Explore the complete parameterization pipeline and more options in the [user manual](MANUAL.md) and browse the [examples directory](https://github.com/caltechmsc/dreid-forge/tree/main/examples) for runnable walkthroughs.
### For Library Developers
DREID-Forge is also available as a library crate. Add it to your `Cargo.toml` dependencies:
```toml
[dependencies]
dreid-forge = "0.4.0"
```
#### Example: Parameterizing a Molecule
```rust
use dreid_forge::{Atom, Bond, BondOrder, Element, System};
use dreid_forge::{forge, ForgeConfig, ChargeMethod, QeqConfig, ForgeError};
fn main() -> Result<(), ForgeError> {
// Build a water molecule
let mut system = System::new();
system.atoms.push(Atom::new(Element::O, [0.0, 0.0, 0.0]));
system.atoms.push(Atom::new(Element::H, [0.9575, 0.0, 0.0]));
system.atoms.push(Atom::new(Element::H, [-0.2399, 0.9272, 0.0]));
system.bonds.push(Bond::new(0, 1, BondOrder::Single));
system.bonds.push(Bond::new(0, 2, BondOrder::Single));
// Parameterize with QEq charges
let config = ForgeConfig {
charge_method: ChargeMethod::Qeq(QeqConfig::default()),
..Default::default()
};
let forged = forge(&system, &config)?;
// Inspect results
println!("Atom types: {:?}", forged.atom_types);
println!("Bonds: {}", forged.potentials.bonds.len());
println!("Angles: {}", forged.potentials.angles.len());
// Oxygen should be negatively charged, hydrogens positive
assert!(forged.atom_properties[0].charge < 0.0);
assert!(forged.atom_properties[1].charge > 0.0);
Ok(())
}
```
#### Example: Reading PDB and Writing BGF
```rust
use std::fs::File;
use std::io::{BufReader, BufWriter};
use dreid_forge::{forge, ForgeConfig};
use dreid_forge::io::{BioReader, Format, CleanConfig, ProtonationConfig, write_bgf};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Read and prepare a PDB structure
let file = File::open("protein.pdb")?;
let system = BioReader::new(BufReader::new(file), Format::Pdb)
.clean(CleanConfig { remove_water: true, remove_ions: true, ..Default::default() })
.protonate(ProtonationConfig::default())
.read()?;
// Parameterize with DREIDING force field
let forged = forge(&system, &ForgeConfig::default())?;
// Write BGF file
let mut output = BufWriter::new(File::create("system.bgf")?);
write_bgf(&mut output, &forged)?;
Ok(())
}
```
#### Example: Hybrid Charges for Protein-Ligand Systems
```rust
use std::fs::File;
use std::io::BufReader;
use dreid_forge::{forge, ForgeConfig, ForgeError};
use dreid_forge::{ChargeMethod, HybridConfig, LigandChargeConfig, LigandQeqMethod};
use dreid_forge::{ResidueSelector, EmbeddedQeqConfig, QeqConfig};
use dreid_forge::io::{BioReader, Format, ProtonationConfig, TopologyConfig};
fn main() -> Result<(), ForgeError> {
// Read a protein-ligand complex
let file = File::open("complex.pdb").unwrap();
let system = BioReader::new(BufReader::new(file), Format::Pdb)
.protonate(ProtonationConfig { target_ph: Some(7.4), ..Default::default() })
.topology(TopologyConfig::default())
.read()
.unwrap();
// Configure hybrid charges:
// - Protein: AMBER ff99SB charges
// - Ligand at chain A, residue 500: embedded QEq (polarized by protein)
let config = ForgeConfig {
charge_method: ChargeMethod::Hybrid(HybridConfig {
ligand_configs: vec![
LigandChargeConfig {
selector: ResidueSelector::new("A", 500, None),
method: LigandQeqMethod::Embedded(EmbeddedQeqConfig {
cutoff_radius: 12.0, // Include protein atoms within 12 Å
qeq: QeqConfig::default(),
}),
},
],
..Default::default()
}),
..Default::default()
};
let forged = forge(&system, &config)?;
// Protein atoms have classical AMBER charges
// Ligand atoms have QEq charges polarized by protein environment
println!("Total atoms: {}", forged.atom_properties.len());
Ok(())
}
```
> **Tip**: For small molecules without biological context, use `ChemReader` with MOL2 or SDF formats instead.
For detailed usage instructions and configuration options, refer to the [API Documentation](https://docs.rs/dreid-forge).
## Documentation
- [CLI User Manual](MANUAL.md) — detailed explanation of command-line usage and options.
- [API Documentation](https://docs.rs/dreid-forge) — comprehensive reference for all public types and functions.
- [Architecture Overview](ARCHITECTURE.md) — detailed explanation of the internal design, algorithms, and data flow.
## Dependencies
`dreid-forge` builds on several specialized crates:
| [`dreid-typer`](https://crates.io/crates/dreid-typer) | DREIDING atom type assignment and topology enumeration |
| [`cheq`](https://crates.io/crates/cheq) | Charge equilibration (QEq) solver with embedded field support |
| [`ffcharge`](https://crates.io/crates/ffcharge) | Classical force field charges for proteins, nucleic acids, water, and ions |
| [`dreid-kernel`](https://crates.io/crates/dreid-kernel) | Stateless DREIDING energy/force kernels with precomputed parameters |
| [`bio-forge`](https://crates.io/crates/bio-forge) | Biomolecular structure preparation (cleaning, protonation, solvation, topology) |
## License
This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.