FreeSolvE: Solvent-Mediated Differentiable Pose Refinement & Biophysical Inductive Bias for PyTorch
FreeSolvE is a differentiable, GPU-accelerated continuum solvation and articulated kinematics engine designed to bridge statistical generative molecular models (DiffDock, AlphaFold3, NeuralPLexer, TANKBind) with physical biophysics at ultra-high computational speed.
⚡ Key Highlights & Benchmark Results
- +50.0% Absolute Gain on Official PoseBusters Benchmark: On 50 diverse co-crystal complexes from the official PoseBusters validation package, FreeSolvE rescues severely clashing generative poses, jumping from 2.0% to 52.0% validity (exceeding raw DiffDock at 36.4%, TANKBind at 24.5%, and EquiBind at 0.3%).
- Ultra-High Speed (2.33s per Target): Completes full pocket clash rescue and energy minimization in an average of 2.33 seconds per target (>18,000× faster than explicit-solvent molecular dynamics).
- Sub-10ms FFT Continuum Solvation: Evaluates the complete 3D Poisson electrostatic potential and SASA cavity field via Fourier convolution in under 8 milliseconds.
- PyTorch Training Layer (
FreeSolvEPhysicsLoss): Seamlessly plugs into PyTorch training loops with < 15 ms overhead per mini-batch step, eliminating generative pocket clashes from 5 down to 0 within 5 epochs. - Zero-Setup Preparation: Operates directly on standard PDB and SDF files without requiring brittle manual topology curation, charge parameterization, or missing hydrogen repair (avoiding OpenMM template failure crashes).
- 100% Invariant Covalent Chemistry: Parameterizes flexibility strictly in internal torsion space ($\mathrm{SO}(3) \times \mathbb{R}^3 \times \mathbb{T}^k$) using forward kinematics, guaranteeing bond lengths and angles remain chemically valid by construction.
📊 Benchmark Figures
1. PoseBusters Physical Validity & Speed Comparison
2. High-Resolution 3D Clash Relief
3. Side-by-Side PyTorch Training Dynamics (MSE vs. FreeSolvE Physics)
🚀 Installation
Install FreeSolvE in editable mode directly from this repository:
git clone https://github.com/messiay/FreeSolve.git
cd FreeSolve
pip install -e .
Requirements
- Python ≥ 3.9
- PyTorch ≥ 2.0
- RDKit
- NumPy, SciPy, PyYAML
💻 Quickstart: Using FreeSolvE in PyTorch
1. Real-Time Physics Loss During Neural Network Training
Incorporate FreeSolvEPhysicsLoss directly into your PyTorch training loop to prevent generative models from producing unphysical steric overlaps:
import torch
import torch.nn as nn
from freesolve import FreeSolvEPhysicsLoss
# 1. Instantiate the differentiable physics loss layer
loss_layer = FreeSolvEPhysicsLoss(
salt_concentration=0.150, # 0.150 M physiological saline
clash_penalty_weight=2.0, # Penalize severe interatomic overlap (< 2.0 A)
vdw_weight=1.0, # Soft-core Lennard-Jones
elec_weight=1.0 # Dielectric-screened electrostatics
)
# 2. Your deep learning model predicts ligand Cartesian coordinates
pred_coords = model(pocket_features, ligand_features) # Shape: (N, 3), requires_grad=True
# 3. Compute differentiable physics loss
phys_outputs = loss_layer(
ligand_coords=pred_coords,
ligand_charges=ligand_charges, # Shape: (N,)
ligand_elements=ligand_elements, # Shape: (N,) atomic numbers
pocket_coords=pocket_coords, # Shape: (M, 3)
pocket_charges=pocket_charges, # Shape: (M,)
pocket_elements=pocket_elements # Shape: (M,) atomic numbers
)
physics_loss = phys_outputs["total_loss"]
clash_count = phys_outputs["clash_count"]
# 4. Total Loss = Coordinate MSE + Biophysical Inductive Bias
total_loss = mse_loss(pred_coords, true_coords) + 0.08 * physics_loss
# 5. Standard PyTorch backward pass
total_loss.backward()
optimizer.step()
2. Convenience Factory from RDKit Molecules
If you have RDKit molecules, you can automatically extract all partial charges, elements, and coordinates with one line:
from rdkit import Chem
from freesolve import FreeSolvEPhysicsLoss
ligand_mol = Chem.SDMolSupplier("pose.sdf")[0]
pocket_mol = Chem.MolFromPDBFile("pocket.pdb")
# Extract tensors and loss layer automatically
loss_layer, tensors = FreeSolvEPhysicsLoss.from_molecules(ligand_mol, pocket_mol)
# Forward pass using your predicted coordinates
loss_dict = loss_layer(
ligand_coords=pred_coords,
**tensors
)
loss_dict["total_loss"].backward()
3. Fast 2-Second Pose Rescue & Induced-Fit Docking
Use FreeSolvE at inference time to instantly rescue clashing poses generated by DiffDock, AlphaFold3, or AutoDock Vina:
from freesolve import dock, relax
# High-speed induced-fit pose rescue (average 2.3 seconds)
result = dock(
receptor="pocket.pdb",
ligand="initial_pose.sdf",
mode="torsional", # Optimizes internal dihedrals + rigid SE(3)
max_steps=25,
lr=0.03
)
print(result.summary())
# Output: DockingResult(clashes: 5 -> 0, loss: 48.2 -> -12.4, time: 2.15s)
# Save refined pose
result.save(ligand_path="rescued_pose.sdf", complex_path="rescued_complex.pdb")
📑 Manuscript & Citation
If you use FreeSolvE in your research, please cite our preprint:
- Word Document:
MANUSCRIPT_FreeSolvE_Preprint.docx - Web & PDF Version:
MANUSCRIPT_FreeSolvE_Preprint.html - Markdown Source:
MANUSCRIPT_FreeSolvE_Preprint.md
@article{arjun2026freesolve,
title={FreeSolvE: Solvent-Mediated Differentiable Pose Refinement and Ultra-Fast Biophysical Inductive Bias for Molecular Generation and Docking},
author={Arjun and collaborators},
journal={bioRxiv / ChemRxiv preprint},
year={2026}
}
📜 License
Distributed under the MIT License. See LICENSE for details.
Metadata
Release files for freesolve 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| freesolve-0.1.0.tar.gz | 123.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| freesolve-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 250.5 kB
Release files / freesolve-0.1.0.tar.gz
| Download URL | freesolve-0.1.0.tar.gz |
|---|---|
| Size | 123.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c141c6ea5560701c223ca47259270e62f3a20235be53bc07805cc045c7cdf474
|
|
BLAKE2b-256 checksum How to use checksums |
45e98864abab6b51c77784c049c4736c07aa0705c87dc0a89340562ef3df0fe1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.3
|
Release files / freesolve-0.1.0-py3-none-any.whl
| Download URL | freesolve-0.1.0-py3-none-any.whl |
|---|---|
| Size | 126.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
483317dc5c6265b3d4060eb68daa4e7525a549d570dd48c74c1437cad4e694e6
|
|
BLAKE2b-256 checksum How to use checksums |
4ce14234ac93e30a34f2fc0b5a64dd23ea4bdd255cbc12dabe32a9b279da9456
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.3
|