1use chematic_core::BondOrder;
2use std::f64::consts::PI;
3
4use crate::dreiding::DREIDINGType;
5
6pub fn dreiding_vdw(t: DREIDINGType) -> (f64, f64) {
7 let (r0, depth) = match t {
8 DREIDINGType::H_ => (2.646, 0.044),
9 DREIDINGType::C_3 => (3.473, 0.066),
10 DREIDINGType::C_2 => (3.473, 0.066),
11 DREIDINGType::C_1 => (3.473, 0.066),
12 DREIDINGType::C_R => (3.473, 0.066),
13 DREIDINGType::N_3 => (3.243, 0.068),
14 DREIDINGType::N_2 => (3.243, 0.068),
15 DREIDINGType::N_1 => (3.243, 0.068),
16 DREIDINGType::N_R => (3.243, 0.068),
17 DREIDINGType::O_3 => (3.144, 0.052),
18 DREIDINGType::O_2 => (3.144, 0.052),
19 DREIDINGType::O_R => (3.144, 0.052),
20 DREIDINGType::S_3 => (3.952, 0.274),
21 DREIDINGType::S_R => (3.952, 0.274),
22 DREIDINGType::P_3 => (3.741, 0.210),
23 DREIDINGType::F_ => (3.048, 0.050),
24 DREIDINGType::Cl => (3.516, 0.227),
25 DREIDINGType::Br => (3.641, 0.389),
26 DREIDINGType::I_ => (3.984, 0.680),
27 DREIDINGType::X_ => (3.473, 0.066),
28 };
29 (r0, depth)
30}
31
32pub fn dreiding_bond_len(t1: DREIDINGType, t2: DREIDINGType, order: BondOrder) -> f64 {
33 let key = (
34 dreiding_type_order(t1),
35 dreiding_type_order(t2),
36 bond_order_value(order),
37 );
38
39 match key {
40 (1, 1, 1) => 1.090,
41 (1, 6, 1) => 1.090,
42 (1, 7, 1) => 1.010,
43 (1, 8, 1) => 0.960,
44 (1, 16, 1) => 1.336,
45 (1, 17, 1) => 0.980,
46 (1, 35, 1) => 1.084,
47 (1, 53, 1) => 1.008,
48
49 (6, 6, 1) => 1.540,
50 (6, 6, 2) => 1.340,
51 (6, 6, 3) => 1.204,
52 (6, 6, 4) => 1.395,
53 (6, 7, 1) => 1.469,
54 (6, 7, 2) => 1.279,
55 (6, 7, 3) => 1.158,
56 (6, 7, 4) => 1.340,
57 (6, 8, 1) => 1.427,
58 (6, 8, 2) => 1.217,
59 (6, 8, 4) => 1.370,
60 (6, 16, 1) => 1.820,
61 (6, 17, 1) => 1.770,
62 (6, 35, 1) => 1.940,
63 (6, 53, 1) => 2.140,
64
65 (7, 7, 1) => 1.450,
66 (7, 7, 2) => 1.225,
67 (7, 7, 3) => 1.098,
68 (7, 8, 1) => 1.400,
69 (7, 8, 2) => 1.218,
70 (7, 16, 1) => 1.754,
71 (7, 17, 1) => 1.690,
72
73 (8, 8, 1) => 1.480,
74 (8, 8, 2) => 1.208,
75 (8, 16, 1) => 1.680,
76 (8, 17, 1) => 1.611,
77
78 (16, 16, 1) => 2.048,
79 (16, 16, 2) => 1.549,
80
81 _ => match order {
82 BondOrder::Triple => 1.20,
83 BondOrder::Double => 1.34,
84 BondOrder::Aromatic => 1.40,
85 _ => 1.54,
86 },
87 }
88}
89
90pub fn dreiding_angle(t: DREIDINGType) -> f64 {
91 let deg = match t {
92 DREIDINGType::C_3 => 109.47,
93 DREIDINGType::C_2 => 120.0,
94 DREIDINGType::C_1 => 180.0,
95 DREIDINGType::C_R => 120.0,
96 DREIDINGType::N_3 => 106.7,
97 DREIDINGType::N_2 => 120.0,
98 DREIDINGType::N_1 => 180.0,
99 DREIDINGType::N_R => 120.0,
100 DREIDINGType::O_3 => 104.51,
101 DREIDINGType::O_2 => 120.0,
102 DREIDINGType::O_R => 120.0,
103 DREIDINGType::S_3 => 99.0,
104 DREIDINGType::S_R => 120.0,
105 DREIDINGType::P_3 => 93.0,
106 DREIDINGType::H_ => 109.47,
107 DREIDINGType::F_ => 109.47,
108 DREIDINGType::Cl => 109.47,
109 DREIDINGType::Br => 109.47,
110 DREIDINGType::I_ => 109.47,
111 DREIDINGType::X_ => 109.47,
112 };
113 deg * PI / 180.0
114}
115
116pub fn dreiding_torsion_barrier(_t1: DREIDINGType, _t2: DREIDINGType) -> f64 {
117 2.0
118}
119
120fn dreiding_type_order(t: DREIDINGType) -> u8 {
121 match t {
122 DREIDINGType::H_ => 1,
123 DREIDINGType::C_3 | DREIDINGType::C_2 | DREIDINGType::C_1 | DREIDINGType::C_R => 6,
124 DREIDINGType::N_3 | DREIDINGType::N_2 | DREIDINGType::N_1 | DREIDINGType::N_R => 7,
125 DREIDINGType::O_3 | DREIDINGType::O_2 | DREIDINGType::O_R => 8,
126 DREIDINGType::S_3 | DREIDINGType::S_R => 16,
127 DREIDINGType::P_3 => 15,
128 DREIDINGType::F_ => 9,
129 DREIDINGType::Cl => 17,
130 DREIDINGType::Br => 35,
131 DREIDINGType::I_ => 53,
132 DREIDINGType::X_ => 0,
133 }
134}
135
136fn bond_order_value(order: BondOrder) -> u8 {
137 match order {
138 BondOrder::Single => 1,
139 BondOrder::Double => 2,
140 BondOrder::Triple => 3,
141 BondOrder::Quadruple => 4,
142 BondOrder::Aromatic => 4,
143 _ => 1,
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use super::*;
150
151 #[test]
152 fn test_vdw_carbon() {
153 let (r0, depth) = dreiding_vdw(DREIDINGType::C_3);
154 assert!((r0 - 3.473).abs() < 0.001);
155 assert!((depth - 0.066).abs() < 0.001);
156 }
157
158 #[test]
159 fn test_bond_len_cc_single() {
160 let r = dreiding_bond_len(DREIDINGType::C_3, DREIDINGType::C_3, BondOrder::Single);
161 assert!((r - 1.540).abs() < 0.001);
162 }
163
164 #[test]
165 fn test_bond_len_cc_double() {
166 let r = dreiding_bond_len(DREIDINGType::C_2, DREIDINGType::C_2, BondOrder::Double);
167 assert!((r - 1.340).abs() < 0.001);
168 }
169
170 #[test]
171 fn test_angle_sp3() {
172 let theta = dreiding_angle(DREIDINGType::C_3);
173 let expected = 109.47 * PI / 180.0;
174 assert!((theta - expected).abs() < 0.01);
175 }
176
177 #[test]
178 fn test_angle_sp2() {
179 let theta = dreiding_angle(DREIDINGType::C_2);
180 let expected = 120.0 * PI / 180.0;
181 assert!((theta - expected).abs() < 0.01);
182 }
183}