00001
00053 #include "apbscfg.h"
00054 #include "maloc/maloc.h"
00055 #include "apbs/apbs.h"
00056
00057 int main(int argc, char **argv) {
00058
00059
00060 Valist *alist = VNULL;
00061 Vatom *atom = VNULL;
00062 Vgreen *green = VNULL;
00063 Vio *sock = VNULL;
00064
00065 double *pos, energy, zmagic, disp[3], force[3];
00066 double *fx, *fy, *fz, *pot, *xp, *yp, *zp, *qp;
00067 int i, j;
00068 int doenergy = 0;
00069 int doforce = 0;
00070
00071
00072 char *path;
00073
00074 char *usage = "\n\n\
00075 This program calculates electrostatic properties using Coulomb's law;\n\
00076 i.e., the Green's function for the Poisson operator in a homogeneous\n\
00077 medium with dielectric constant 1 (vacumm). It is very important to\n\
00078 realize that all energies, forces, etc. are calculated with this\n\
00079 dielectric constant of 1 and must be scaled to be compared with other\n\
00080 calculations.\n\n\
00081 Usage: coulomb [-e] [-f] <molecule.pqr>\n\n\
00082 where <molecule.pqr> is the path to the molecule\n\
00083 structure in PQR format. By default the total energies and forces\n\
00084 will be printed. This program also supports the following options:\n\
00085 -e give per-atom energies\n\
00086 -f give per-atom forces\n\n";
00087
00088 Vio_start();
00089
00090 if ((argc > 4) || (argc < 2)) {
00091 Vnm_print(2, "\n*** Syntax error: got %d arguments, expected 2.\n",
00092 argc);
00093 Vnm_print(2, "%s", usage);
00094 exit(666);
00095 };
00096 if (argc > 2) {
00097 for (i=1; i<(argc-1); i++) {
00098 if (strcmp("-e", argv[i]) == 0) {
00099 Vnm_print(1, "Providing per-atom energies...\n");
00100 doenergy = 1;
00101 } else if (strcmp("-f", argv[i]) == 0) {
00102 Vnm_print(1, "Providing per-atom forces...\n");
00103 doforce = 1;
00104 } else if (strcmp("-ef", argv[i]) == 0 || \
00105 strcmp("-fe", argv[i]) == 0){
00106 Vnm_print(1, "Providing per-atom forces and energies...\n");
00107 doforce = 1;
00108 doenergy = 1;
00109
00110 } else {
00111 Vnm_print(2, "Ignoring option %s\n", argv[i]);
00112 }
00113 }
00114 path = argv[argc-1];
00115 } else {
00116 path = argv[1];
00117 }
00118
00119 Vnm_print(1, "Setting up atom list from %s.\n", path);
00120 alist = Valist_ctor();
00121 sock = Vio_ctor("FILE", "ASC", VNULL, path, "r");
00122 if (sock == VNULL) {
00123 Vnm_print(2, "Problem opening virtual socket %s!\n",
00124 path);
00125 return 0;
00126 }
00127 if (Vio_accept(sock, 0) < 0) {
00128 Vnm_print(2, "Problem accepting virtual socket %s!\n",
00129 path);
00130 return 0;
00131 }
00132 Valist_readPQR(alist,VNULL,sock);
00133 Vnm_print(1, "Read %d atoms\n", Valist_getNumberAtoms(alist));
00134
00135 Vnm_print(1, "Setting up Green's function object.\n");
00136 green = Vgreen_ctor(alist);
00137
00138
00139 Vnm_print(1, "Dielectric constant = 1 (vacuum)\n");
00140 Vnm_print(1, "Distances in Angstroms\n");
00141 Vnm_print(1, "Charges in electrons\n");
00142 zmagic = (1e-3)*Vunit_ec*Vunit_Na;
00143 energy = 0.0;
00144 force[0] = 0.0; force[1] = 0.0; force[2] = 0.0;
00145
00146 Vnm_print(1, "Allocating space for solution...\n");
00147 fx = Vmem_malloc(VNULL, Valist_getNumberAtoms(alist), sizeof(double));
00148 fy = Vmem_malloc(VNULL, Valist_getNumberAtoms(alist), sizeof(double));
00149 fz = Vmem_malloc(VNULL, Valist_getNumberAtoms(alist), sizeof(double));
00150 pot = Vmem_malloc(VNULL, Valist_getNumberAtoms(alist), sizeof(double));
00151 xp = Vmem_malloc(VNULL, Valist_getNumberAtoms(alist), sizeof(double));
00152 yp = Vmem_malloc(VNULL, Valist_getNumberAtoms(alist), sizeof(double));
00153 zp = Vmem_malloc(VNULL, Valist_getNumberAtoms(alist), sizeof(double));
00154 qp = Vmem_malloc(VNULL, Valist_getNumberAtoms(alist), sizeof(double));
00155 for (i=0; i<Valist_getNumberAtoms(alist); i++) {
00156 fx[i] = 0.0;
00157 fy[i] = 0.0;
00158 fz[i] = 0.0;
00159 pot[i] = 0.0;
00160 atom = Valist_getAtom(alist, i);
00161 pos = Vatom_getPosition(atom);
00162 xp[i] = pos[0];
00163 yp[i] = pos[1];
00164 zp[i] = pos[2];
00165 qp[i] = Vatom_getCharge(atom);
00166 }
00167
00168 Vnm_print(1, "Calculating...\n");
00169 Vgreen_coulombD(green, Valist_getNumberAtoms(alist), xp, yp, zp,
00170 pot, fx, fy, fz);
00171
00172 for (i=0; i<Valist_getNumberAtoms(alist); i++) {
00173 fx[i] *= (-0.5*qp[i]*zmagic);
00174 fy[i] *= (-0.5*qp[i]*zmagic);
00175 fz[i] *= (-0.5*qp[i]*zmagic);
00176 pot[i] *= (0.5*qp[i]*zmagic);
00177 energy += pot[i];
00178 force[0] += fx[i];
00179 force[1] += fy[i];
00180 force[2] += fz[i];
00181 if (doenergy) {
00182 Vnm_print(1, "\tAtom %d: Energy = %1.12E kJ/mol\n", i+1, pot[i]);
00183 }
00184 if (doforce) {
00185 Vnm_print(1, "\tAtom %d: x-force = %1.12E kJ/mol/A\n", i+1,
00186 fx[i]);
00187 Vnm_print(1, "\tAtom %d: y-force = %1.12E kJ/mol/A\n", i+1,
00188 fy[i]);
00189 Vnm_print(1, "\tAtom %d: z-force = %1.12E kJ/mol/A\n", i+1,
00190 fz[i]);
00191 }
00192 }
00193
00194 Vnm_print(1, "\n\n-------------------------------------------------------\n");
00195 Vnm_print(1, "Total energy = %1.12e kJ/mol in vacuum.\n", energy);
00196 Vnm_print(1, "Total x-force = %1.12e kJ/mol/A in vacuum.\n", force[0]);
00197 Vnm_print(1, "Total y-force = %1.12e kJ/mol/A in vacuum.\n", force[1]);
00198 Vnm_print(1, "Total z-force = %1.12e kJ/mol/A in vacuum.\n", force[2]);
00199
00200 Vmem_free(VNULL, Valist_getNumberAtoms(alist), sizeof(double),
00201 (void **)&fx);
00202 Vmem_free(VNULL, Valist_getNumberAtoms(alist), sizeof(double),
00203 (void **)&fy);
00204 Vmem_free(VNULL, Valist_getNumberAtoms(alist), sizeof(double),
00205 (void **)&fz);
00206 Vmem_free(VNULL, Valist_getNumberAtoms(alist), sizeof(double),
00207 (void **)&pot);
00208 Vmem_free(VNULL, Valist_getNumberAtoms(alist), sizeof(double),
00209 (void **)&xp);
00210 Vmem_free(VNULL, Valist_getNumberAtoms(alist), sizeof(double),
00211 (void **)&yp);
00212 Vmem_free(VNULL, Valist_getNumberAtoms(alist), sizeof(double),
00213 (void **)&zp);
00214 Vmem_free(VNULL, Valist_getNumberAtoms(alist), sizeof(double),
00215 (void **)&qp);
00216 Vgreen_dtor(&green);
00217 Valist_dtor(&alist);
00218
00219 return 0;
00220 }