Skip to content

Commit 44e4dcb

Browse files
committed
Urey-Bradley potential
1 parent 602bac1 commit 44e4dcb

File tree

4 files changed

+87
-0
lines changed

4 files changed

+87
-0
lines changed

docs/src/documentation.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,7 @@ The available specific interactions are:
582582
- [`FENEBond`](@ref) - 2 atoms
583583
- [`HarmonicAngle`](@ref) - 3 atoms
584584
- [`CosineAngle`](@ref) - 3 atoms
585+
- [`UreyBradley`](@ref) - 3 atoms
585586
- [`PeriodicTorsion`](@ref) - 4 atoms
586587
- [`RBTorsion`](@ref) - 4 atoms
587588

src/Molly.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ include("interactions/morse_bond.jl")
4848
include("interactions/fene_bond.jl")
4949
include("interactions/harmonic_angle.jl")
5050
include("interactions/cosine_angle.jl")
51+
include("interactions/urey_bradley.jl")
5152
include("interactions/periodic_torsion.jl")
5253
include("interactions/rb_torsion.jl")
5354
include("interactions/implicit_solvent.jl")

src/interactions/urey_bradley.jl

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
export UreyBradley
2+
3+
@doc raw"""
4+
UreyBradley(; kangle, θ0, kbond, r0)
5+
6+
An interaction between three atoms consisting of a harmonic bond angle
7+
and a harmonic bond between the outer atoms.
8+
9+
`θ0` is in radians.
10+
The second atom is the middle atom.
11+
The potential energy is defined as
12+
```math
13+
V(\theta, r) = \frac{1}{2} kangle (\theta - \theta_0)^2 + \frac{1}{2} kbond (r - r_0)^2
14+
```
15+
"""
16+
@kwdef struct UreyBradley{KA, A, KB, D}
17+
kangle::KA
18+
θ0::A
19+
kbond::KB
20+
r0::D
21+
end
22+
23+
function Base.zero(::UreyBradley{KA, A, KB, D}) where {KA, A, KB, D}
24+
return UreyBradley(kangle=zero(KA), θ0=zero(A), kbond=zero(KB), r0=zero(D))
25+
end
26+
27+
function Base.:+(a1::UreyBradley, a2::UreyBradley)
28+
return UreyBradley(kangle=(a1.kangle + a2.kangle), θ0=(a1.θ0 + a2.θ0),
29+
kbond=(a1.kbond + a2.kbond), r0=(a1.r0 + a2.r0))
30+
end
31+
32+
@inline function force(a::UreyBradley, coords_i, coords_j, coords_k, boundary, args...)
33+
# In 2D we use then eliminate the cross product
34+
ba = vector_pad3D(coords_j, coords_i, boundary)
35+
bc = vector_pad3D(coords_j, coords_k, boundary)
36+
cross_ba_bc = ba × bc
37+
if iszero_value(cross_ba_bc)
38+
zf = zero(a.kangle ./ trim3D(ba, boundary))
39+
fa, fb, fc = zf, zf, zf
40+
else
41+
pa = normalize(trim3D( ba × cross_ba_bc, boundary))
42+
pc = normalize(trim3D(-bc × cross_ba_bc, boundary))
43+
angle_term = -a.kangle * (acosbound(dot(ba, bc) / (norm(ba) * norm(bc))) - a.θ0)
44+
fa = (angle_term / norm(ba)) * pa
45+
fc = (angle_term / norm(bc)) * pc
46+
fb = -fa - fc
47+
end
48+
vec_ik = vector(coords_i, coords_k, boundary)
49+
c = a.kbond * (norm(vec_ik) - a.r0)
50+
f = c * normalize(vec_ik)
51+
fa += f
52+
fc -= f
53+
return SpecificForce3Atoms(fa, fb, fc)
54+
end
55+
56+
@inline function potential_energy(a::UreyBradley, coords_i, coords_j,
57+
coords_k, boundary, args...)
58+
θ = bond_angle(coords_i, coords_j, coords_k, boundary)
59+
rik = norm(vector(coords_i, coords_k, boundary))
60+
return (a.kangle / 2) *- a.θ0) ^ 2 + (a.kbond / 2) * (rik - a.r0) ^ 2
61+
end

test/interactions.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,30 @@
486486
atol=1e-9u"kJ * mol^-1",
487487
)
488488

489+
a1 = UreyBradley(kangle=300.0u"kJ * mol^-1", θ0=0.8,
490+
kbond=10_000.0u"kJ * mol^-1 * nm^-2", r0=0.3u"nm")
491+
fs = force(a1, c1, c2, c3a, boundary)
492+
@test isapprox(
493+
fs.f1,
494+
SVector(0.0, -152.4546720285, -152.4546720285)u"kJ * mol^-1 * nm^-1";
495+
atol=1e-9u"kJ * mol^-1 * nm^-1",
496+
)
497+
@test isapprox(
498+
fs.f2,
499+
SVector(-21.9771730369, 14.6514486912, 14.6514486912)u"kJ * mol^-1 * nm^-1";
500+
atol=1e-9u"kJ * mol^-1 * nm^-1",
501+
)
502+
@test isapprox(
503+
fs.f3,
504+
SVector(21.9771730369, 137.8032233372, 137.8032233372)u"kJ * mol^-1 * nm^-1";
505+
atol=1e-9u"kJ * mol^-1 * nm^-1",
506+
)
507+
@test isapprox(
508+
potential_energy(a1, c1, c2, c3a, boundary),
509+
1.7626664989u"kJ * mol^-1";
510+
atol=1e-9u"kJ * mol^-1",
511+
)
512+
489513
inter = MullerBrown()
490514
local_min_1 = SVector( 0.6234994049304005, 0.028037758528718367)u"nm"
491515
local_min_2 = SVector(-0.05001082299878202, 0.46669410487256247)u"nm"

0 commit comments

Comments
 (0)