ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-2.0/src/openbabel/molchrg.cpp
Revision: 2518
Committed: Fri Dec 16 21:52:50 2005 UTC (18 years, 6 months ago) by tim
File size: 8401 byte(s)
Log Message:
changed __FUNCTION__ to __func__ to match C99 standard, and then added
an autoconf test to check for __func__ usability.  Changed some default
compile flags for the Sun architecture

File Contents

# Content
1 /**********************************************************************
2 molchrg.cpp - Assign Gasteiger partial charges.
3
4 Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
5 Some portions Copyright (C) 2001-2005 by Geoffrey R. Hutchison
6
7 This file is part of the Open Babel project.
8 For more information, see <http://openbabel.sourceforge.net/>
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation version 2 of the License.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 ***********************************************************************/
19
20 #include "mol.hpp"
21 #include "molchrg.hpp"
22
23 using namespace std;
24 namespace OpenBabel
25 {
26
27 /*! \class OBGastChrg
28 \brief Assigns Gasteiger partial charges
29
30 The OBGastChrg class is responsible for the assignment of partial
31 charges to a molecule according to the Gasteiger charge model (sigma). When
32 the partial charge of an atom is requested and partial charges do not
33 yet exist for the molecule the OBGastChrg class will automatically be
34 called to assign charges for the molecule. If charges have been read
35 in for a molecule the following code shows how to force the
36 recalculation of partial charges:
37 \code
38 OBMol mol;
39
40 mol.UnsetPartialChargesPerceived();
41 FOR_ATOMS_IN_MOL(atom, mol)
42 {
43 cout << "atom number = " << atom->GetIdx();
44 cout << " charge = " << atom->GetPartialCharge() << endl;
45 }
46 \endcode
47 Formal charges are used as seed values of the initial charge of atoms,
48 and the partial charge is propagated to neighboring atoms. For
49 example, quaternary amines would have a +1 charge, and the effect of
50 the positive charge would be felt by neighboring atoms according to
51 the Gasteiger model (sigma).
52
53 For more information, see:
54 J. Gasteiger & M. Marsili, "A New Model for Calculating Atomic Charges in Molecules" Tetrahedron Lett., (1978) 3181-3184.
55 */
56
57 bool OBGastChrg::AssignPartialCharges(OBMol &mol)
58 {
59 //InitialPartialCharges(mol);
60 obErrorLog.ThrowError(__func__,
61 "Ran OpenBabel::AssignPartialCharges", obAuditMsg);
62
63 OBAtom *atom;
64 vector<OBNodeBase*>::iterator i;
65
66 GSVResize(mol.NumAtoms()+1);
67 double a,b,c;
68 for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i))
69 {
70 if (!GasteigerSigmaChi(atom,a,b,c))
71 return(false);
72 _gsv[atom->GetIdx()]->SetValues(a,b,c,atom->GetPartialCharge());
73 }
74
75 double alpha,charge,denom;
76 unsigned j;
77 int iter;
78 OBBond *bond;
79 OBAtom *src,*dst;
80 vector<OBEdgeBase*>::iterator k;
81 alpha = 1.0;
82 for(iter = 0;iter < OB_GASTEIGER_ITERS;iter++)
83 {
84 alpha *= OB_GASTEIGER_DAMP;
85
86 for( j=1;j < _gsv.size();j++)
87 {
88 charge = _gsv[j]->q;
89 _gsv[j]->chi = (_gsv[j]->c*charge+_gsv[j]->b)*charge+_gsv[j]->a;
90 }
91
92 for (bond = mol.BeginBond(k);bond;bond = mol.NextBond(k))
93 {
94 src = bond->GetBeginAtom();
95 dst = bond->GetEndAtom();
96
97 if (_gsv[src->GetIdx()]->chi >= _gsv[dst->GetIdx()]->chi)
98 {
99 if (dst->IsHydrogen())
100 denom = double(OB_GASTEIGER_DENOM);
101 else
102 denom = _gsv[dst->GetIdx()]->denom;
103 }
104 else
105 {
106 if (src->IsHydrogen())
107 denom = double(OB_GASTEIGER_DENOM);
108 else
109 denom = _gsv[src->GetIdx()]->denom;
110 }
111
112 charge = (_gsv[src->GetIdx()]->chi - _gsv[dst->GetIdx()]->chi)/denom;
113 _gsv[src->GetIdx()]->q -= alpha*charge;
114 _gsv[dst->GetIdx()]->q += alpha*charge;
115 }
116 }
117
118 for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i))
119 atom->SetPartialCharge(_gsv[atom->GetIdx()]->q);
120
121 return(true);
122 }
123
124 void OBGastChrg::InitialPartialCharges(OBMol &mol)
125 {
126 OBAtom *atom;
127 vector<OBNodeBase*>::iterator i;
128
129 for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i))
130 {
131 if (atom->IsCarboxylOxygen())
132 atom->SetPartialCharge(-0.500);
133 else if (atom->IsPhosphateOxygen() &&
134 atom->GetHvyValence() == 1)
135 atom->SetPartialCharge(-0.666);
136 else if (atom->IsSulfateOxygen())
137 atom->SetPartialCharge(-0.500);
138 else
139 atom->SetPartialCharge((double)atom->GetFormalCharge());
140 }
141 }
142
143 bool OBGastChrg::GasteigerSigmaChi(OBAtom *atom,double &a,double &b,double &c )
144 {
145 int count;
146 double val[3] = {0.0,0.0,0.0};
147
148 switch(atom->GetAtomicNum())
149 {
150 case 1: //H
151 val[0] = 0.37;
152 val[1] = 7.17;
153 val[2] = 12.85;
154 break;
155 case 6: //C
156 if (atom->GetHyb() == 3)
157 {
158 val[0] = 0.68;
159 val[1] = 7.98;
160 val[2] = 19.04;
161 }
162 if (atom->GetHyb() == 2)
163 {
164 val[0] = 0.98;
165 val[1] = 8.79;
166 val[2] = 19.62;
167 }
168 if (atom->GetHyb() == 1)
169 {
170 val[0] = 1.67;
171 val[1] = 10.39;
172 val[2] = 20.57;
173 }
174 break;
175 case 7: //N
176 if (atom->GetHyb() == 3)
177 {
178 if (atom->GetValence() == 4 || atom->GetFormalCharge())
179 {
180 val[0] = 0.0;
181 val[1] = 0.0;
182 val[2] = 23.72;
183 }
184 else
185 {
186 val[0] = 2.08;
187 val[1] = 11.54;
188 val[2] = 23.72;
189 }
190 }
191
192 if (atom->GetHyb() == 2)
193 {
194 if (EQ(atom->GetType(),"Npl") || EQ(atom->GetType(),"Nam"))
195 {
196 val[0] = 2.46;
197 val[1] = 12.32;
198 val[2] = 24.86;
199 }
200 else
201 {
202 val[0] = 2.57;
203 val[1] = 12.87;
204 val[2] = 24.87;
205 }
206 }
207
208 if (atom->GetHyb() == 1)
209 {
210 val[0] = 3.71;
211 val[1] = 15.68;
212 val[2] = 27.11;
213 }
214 break;
215 case 8: //O
216 if (atom->GetHyb() == 3)
217 {
218 val[0] = 2.65;
219 val[1] = 14.18;
220 val[2] = 28.49;
221 }
222 if (atom->GetHyb() == 2)
223 {
224 val[0] = 3.75;
225 val[1] = 17.07;
226 val[2] = 31.33;
227 }
228 break;
229 case 9: //F
230 val[0] = 3.12;
231 val[1] = 14.66;
232 val[2] = 30.82;
233 break;
234 case 15: //P
235 val[0] = 1.62;
236 val[1] = 8.90;
237 val[2] = 18.10;
238 break;
239 case 16: //S
240 count = atom->CountFreeOxygens();
241 if (count == 0 || count == 1)
242 {
243 val[0] = 2.39;
244 val[1] = 10.14;
245 val[2] = 20.65;
246 }
247 if (count > 1)
248 {
249 val[0] = 2.39;
250 val[1] = 12.00;
251 val[2] = 24.00;
252 }
253 /*S2? if (count == 0) {val[0] = 2.72;val[1] = 10.88;val[2] = 21.69;}*/
254 break;
255 case 17: //Cl
256 val[0] = 2.66;
257 val[1] = 11.00;
258 val[2] = 22.04;
259 break;
260 case 35: //Br
261 val[0] = 2.77;
262 val[1] = 10.08;
263 val[2] = 19.71;
264 break;
265 case 53: //I
266 val[0] = 2.90;
267 val[1] = 9.90;
268 val[2] = 18.82;
269 break;
270 case 13: //Al
271 val[0] = 1.06;
272 val[1] = 5.47;
273 val[2] = 11.65;
274 break;
275 }
276
277 if (!IsNearZero(val[2]))
278 {
279 a = val[1];
280 b = (val[2]-val[0])/2;
281 c = (val[2]+val[0])/2 - val[1];
282 }
283 else
284 return(false);
285
286 return(true);
287 }
288
289 void OBGastChrg::GSVResize(int size)
290 {
291 vector <GasteigerState*>::iterator i;
292 for (i = _gsv.begin();i != _gsv.end();i++)
293 delete *i;
294 _gsv.clear();
295
296 for (int j = 0;j < size;j++)
297 _gsv.push_back(new GasteigerState);
298 }
299
300 OBGastChrg::~OBGastChrg()
301 {
302 vector <GasteigerState*>::iterator i;
303 for (i = _gsv.begin();i != _gsv.end();i++)
304 delete *i;
305 }
306
307 GasteigerState::GasteigerState()
308 {
309 a = 0.0;
310 b = 0.0;
311 c = 0.0;
312 denom = 0.0;
313 chi = 0.0;
314 q = 0.0;
315 }
316
317 } // end namespace OpenBabel
318
319 //! \file molchrg.cpp
320 //! \brief Assign Gasteiger partial charges.