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

# User Rev Content
1 tim 2440 /**********************************************************************
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 tim 2518 obErrorLog.ThrowError(__func__,
61 tim 2440 "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.