引力指標
ニュートンが発見した万有引力の法則、
すなわち、2つの物体の質量をM、m、物体間の距離をr、万有引力定数をGとして、
物体間にはたらく力 F = G x M x m / r^2
と表せることは、古典力学のもっとも基本的な公式なひとつです。
Katritzkyら*1は、すべての原子間について、
M x m / r^2
を計算し、これを足し合わせて引力指標(gravitational index)としました。
そして、この値と沸点との相関性を確認したのでした。
- GRAV = Σ(M x m / r^2)
もうここまでくると直感的に原理を解釈できませんが、
先に式を示しておくとゴールが見えやすくなることもありますので、
これはこれで良いのかもしれません(妥協)。
CDKの実装では、9種類の値が算出されます。
- heavysum : 結合が存在し、かつ双方とも重原子である原子間について計算
- heavysumの二乗根
- heavysumの三乗根
- sum : 結合が存在する原子間(水素原子を含む)について計算
- sumの二乗根
- sumの三乗根
- allheavysum : すべての原子間で計算
- allheavysumの二乗根
- allheavysumの三乗根
/* gravity.java */import java.io.*;
import org.openscience.cdk.interfaces.*;
import org.openscience.cdk.io.iterator.IteratingMDLReader;
import org.openscience.cdk.DefaultChemObjectBuilder;import org.openscience.cdk.config.IsotopeFactory;
import org.openscience.cdk.geometry.GeometryTools;
import javax.vecmath.Point3d;
import java.util.ArrayList;class gravity {
public static void main(String args[]){
if(args.length!=1){
System.err.println("gravity <sd-file>");
System.exit(1);
}
FileInputStream fis = null;
IteratingMDLReader isr = null;
try{
fis = new FileInputStream(new File(args[0]) );
isr = new IteratingMDLReader(fis, DefaultChemObjectBuilder.getInstance() );
} catch (Exception e) {
e.printStackTrace();
}while( isr.hasNext() ){
IMolecule imol = (IMolecule)isr.next();
String id = (String)imol.getProperty("cdk:Title");IsotopeFactory factory = null;
double mass1;
double mass2;
try {
factory = IsotopeFactory.getInstance(imol.getBuilder());
} catch (Exception e1) {
//logger.debug(e);
e1.printStackTrace();
}double sum = 0;
for (int i = 0; i < imol.getBondCount(); i++) {
IBond bond = imol.getBond(i);if (bond.getAtomCount() != 2) {
System.err.println("ERROR: Only handles 2 center bonds");
}mass1 = factory.getMajorIsotope( bond.getAtom(0).getSymbol()
).getMassNumber();
mass2 = factory.getMajorIsotope( bond.getAtom(1).getSymbol()
).getMassNumber();Point3d p1 = bond.getAtom(0).getPoint3d();
Point3d p2 = bond.getAtom(1).getPoint3d();double x1 = p1.x;
double y1 = p1.y;
double z1 = p1.z;
double x2 = p2.x;
double y2 = p2.y;
double z2 = p2.z;double dist = (x1 - x2) * (x1 - x2) +
(y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2);
sum += (mass1 * mass2) / dist;
}// heavy atoms only
double heavysum = 0;
for (int i = 0; i < imol.getBondCount(); i++) {
IBond b = imol.getBond(i);if (b.getAtomCount() != 2) {
System.err.println("ERROR: Only handles 2 center bonds");
}if (b.getAtom(0).getSymbol().equals("H") ||
b.getAtom(1).getSymbol().equals("H")) continue;
mass1 = factory.getMajorIsotope(b.getAtom(0).getSymbol()
).getMassNumber();
mass2 = factory.getMajorIsotope(b.getAtom(1).getSymbol()
).getMassNumber();Point3d point0 = b.getAtom(0).getPoint3d();
Point3d point1 = b.getAtom(1).getPoint3d();double x1 = point0.x;
double y1 = point0.y;
double z1 = point0.z;
double x2 = point1.x;
double y2 = point1.y;
double z2 = point1.z;double dist = (x1 - x2) * (x1 - x2) +
(y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2);
heavysum += (mass1 * mass2) / dist;
}// all pairs
ArrayList<Integer> x = new ArrayList<Integer>();
for (int i = 0; i < imol.getAtomCount(); i++) {
if (!imol.getAtom(i).getSymbol().equals("H")) x.add(i);
}
int npair = x.size() * (x.size() - 1) / 2;
pair[] p = new pair[npair];
for (int i = 0; i < npair; i++) p[i] = new pair();
int pcount = 0;
for (int i = 0; i < x.size() - 1; i++) {
for (int j = i + 1; j < x.size(); j++) {
int present = 0;
int a = x.get(i);
int b = x.get(j);
for (int k = 0; k < pcount; k++) {
if ((p[k].x == a && p[k].y == b) ||
(p[k].y == a && p[k].x == b)) present = 1;
}
if (present == 1) continue;
p[pcount].x = a;
p[pcount].y = b;
pcount += 1;
}
}
double allheavysum = 0;
for (pair aP : p) {
int atomNumber1 = aP.x;
int atomNumber2 = aP.y;mass1 = factory.getMajorIsotope(imol.getAtom(atomNumber1).getSymbol()
).getMassNumber();
mass2 = factory.getMajorIsotope(imol.getAtom(atomNumber2).getSymbol()
).getMassNumber();double x1 = imol.getAtom(atomNumber1).getPoint3d().x;
double y1 = imol.getAtom(atomNumber1).getPoint3d().y;
double z1 = imol.getAtom(atomNumber1).getPoint3d().z;
double x2 = imol.getAtom(atomNumber2).getPoint3d().x;
double y2 = imol.getAtom(atomNumber2).getPoint3d().y;
double z2 = imol.getAtom(atomNumber2).getPoint3d().z;double dist = (x1 - x2) * (x1 - x2) +
(y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2);
allheavysum += (mass1 * mass2) / dist;
}
System.out.printf("%s", id);
System.out.printf("\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\n",
heavysum, Math.sqrt(heavysum), Math.pow(heavysum, 1.0/3.0),
sum, Math.sqrt(sum), Math.pow(sum, 1.0/3.0),
allheavysum, Math.sqrt(allheavysum),
Math.pow(allheavysum, 1.0 / 3.0) );
}
}
static private class pair {
int x, y;
public pair() {
x = 0;
y = 0;
}
}
}
*1: Katritzky et al. Correlation of Boiling Points With Molecular Structure. 1. A Training Set of 298 Diverse Organics and a Test Set of 9 Simple Inorganics. J. Phys. Chem. (1996) 100, 10400-10407.