System Building
System Building
Section titled “System Building”FBTK automates the creation of initial structures (unit cells), which is often the first bottleneck in molecular simulation.
Built-in 3D Structure Generation (SMILES to 3D)
Section titled “Built-in 3D Structure Generation (SMILES to 3D)”FBTK features a native Rust engine to generate 3D coordinates directly from SMILES strings. It produces chemically reasonable initial structures in two steps without requiring RDKit:
- VSEPR Theory: Determines initial bond angles and stereochemistry based on Valence Shell Electron Pair Repulsion theory.
- UFF Optimization: Rapidly relaxes bond lengths and strain using the Universal Force Field (UFF).
This allows you to create 3D templates ready for MD simulation from just a single line of text.
Basic Usage
Section titled “Basic Usage”The standard workflow for building a unit cell with a target density using SMILES strings.
import fbtk
# 1. Initialize the builderbuilder = fbtk.Builder(density=0.8)
# 2. Create a molecule template from SMILES and add it with a count# (3D generation via VSEPR + UFF is executed automatically)water = fbtk.Molecule.from_smiles("O", name="WAT")builder.add_molecule(water, count=500)
# 3. Build the systemsystem = builder.build()
# 4. Global relaxation to resolve overlaps (verbose=True by default)system.relax()
# 5. Save the resultsystem.to_file("system.mol2")Molecule Beautify (Relaxation)
Section titled “Molecule Beautify (Relaxation)”When importing molecules from files (.mol or .mol2), the coordinates may not be ideal. You can refine the geometry of a single molecule before adding it to the system.
# Load from a file (which may have unoptimized coordinates)mol = fbtk.Molecule.from_file("raw_structure.mol")
# Refine the structure standalone to ensure chemical correctnessmol.relax()
# Add the refined molecule to the builderbuilder.add_molecule(mol, count=100)Mixing Multiple Components
Section titled “Mixing Multiple Components”You can easily build systems containing multiple types of molecules, such as solvents and solutes.
import fbtk
builder = fbtk.Builder(box_size=[40, 40, 40])
# Add multiple types of small moleculeswater = fbtk.Molecule.from_smiles("O", name="WAT")ethanol = fbtk.Molecule.from_smiles("CCO", name="EtOH")
builder.add_molecule(water, count=800)builder.add_molecule(ethanol, count=200)
system = builder.build()Polymer Generation
Section titled “Polymer Generation”FBTK provides high-speed generation of polymer chains from monomer SMILES strings.
1. RadonPy-style SMILES (Recommended)
Section titled “1. RadonPy-style SMILES (Recommended)”Include * (asterisk) in the SMILES string to automatically specify connection sites.
# '*' are connection sites. Adjacent hydrogens are automatically removed.builder.add_polymer( name="PS", smiles="*C(C*)c1ccccc1", count=10, degree=20)2. Explicit Specification via Indices
Section titled “2. Explicit Specification via Indices”Specify the indices of the heavy atoms involved in polymerization (0-indexed).
# Use the 0th Carbon (Head) and 1st Carbon (Tail) as connection sitesbuilder.add_polymer( name="PS", smiles="CCc1ccccc1", count=10, degree=20, head=0, tail=1)3. Tacticity Control
Section titled “3. Tacticity Control”You can control the stereochemical arrangement (tacticity) of the polymer chain using the tacticity parameter. FBTK automatically determines the side-chain orientation using a center-of-mass analysis and applies mirroring to repeating units.
Supported values:
"isotactic"(Default): All units have the same orientation."syndiotactic": Orientations alternate between adjacent units."atactic": Orientations are assigned randomly.
# Generate Syndiotactic Polystyrenebuilder.add_polymer( name="PS-syn", smiles="*C(C*)c1ccccc1", count=10, degree=50, tacticity="syndiotactic")4. Standalone Polymer Chain
Section titled “4. Standalone Polymer Chain”If you want to create a single polymer chain as a Molecule object (e.g., for saving to a .mol file), use Molecule.from_polymer().
monomer = fbtk.Molecule.from_smiles("*C(C*)c1ccccc1", name="PS")
# Create a 20-mer Atactic chainchain = fbtk.Molecule.from_polymer(monomer, degree=20, tacticity="atactic")
# Save to a file without unit cell informationchain.to_file("ps_chain.mol")Placement Mechanism (Collision-aware Placement)
Section titled “Placement Mechanism (Collision-aware Placement)”FBTK uses a robust grid-based algorithm to place molecules in the unit cell while minimizing initial overlaps. This is critical for preventing “interlocked” ring structures (e.g., benzene rings threading through each other) and ensuring a stable start for structural relaxation.
How it works:
Section titled “How it works:”- Grid Generation: FBTK calculates an optimal 3D grid based on the number of molecules and the box size.
- Spatial Search: For each molecule, FBTK identifies a candidate grid point. If a collision is detected, it tries up to 15 different grid locations.
- Rotation Search: At each candidate location, the molecule is assigned a random 3D orientation. If a collision is detected, it retries with up to 8 different random rotations.
- Collision Detection: Collisions are checked between heavy atoms (non-hydrogen) using a 2.5 Å threshold, accounting for Periodic Boundary Conditions (PBC).
- Fallback: If no collision-free spot is found after 120 attempts (15 locations × 8 rotations), the molecule is placed at the first available grid point, and a warning is issued.
Handling Placement Warnings
Section titled “Handling Placement Warnings”If you see a message like Warning: Possible overlap detected for molecule X (Name), it means the system is very dense, and FBTK could not find a completely collision-free spot for that molecule.
While the subsequent system.relax() (UFF optimization) is highly effective at resolving these overlaps, extremely high-density systems may remain unstable. If relaxation fails or the final energy is excessively high, consider:
- Lowering the target density
- Increasing the box size
- Performing more relaxation steps (
system.relax(steps=2000))