| Bsoft 2.0.5 Bernard's software package

mol_md.cpp
Go to the documentation of this file.
1
9 #include "mol_md.h"
10 #include "mol_bonds.h"
11 #include "rwmolecule.h"
12 #include "random_numbers.h"
13 #include "Matrix.h"
14 #include "linked_list.h"
15 #include "utilities.h"
16
17 // Declaration of global variables
18 extern int verbose; // Level of output to the screen
19
38 double md_leapfrog(Bmolgroup* molgroup, Bmd* md, int max_iter, double velocitylimit)
39 {
40 if ( max_iter < 1 ) return 1e10;
41
42 Bmolecule* mol;
43 Bresidue* res;
44 Batom* atom;
45 Bbond* bondlist = molgroup->bond;
46 Bangle* anglelist = molgroup->angle;
47
48 int cycle = 0;
49 double E(0), dE(0), vel;
50 double timestep = md->timestep;
51 double Kfriction = md->Kfriction;
52 double minvel = -velocitylimit, maxvel = velocitylimit; // Maximum velocity per time step
53
54 random_seed();
55
56 if ( !bondlist ) {
57 error_show("Error in md_leapfrog: No bond list!", __FILE__, __LINE__);
58 return 1e10;
59 }
60
61 if ( !anglelist && md->Kangle ) {
62 error_show("Error in md_leapfrog: No angle list!", __FILE__, __LINE__);
63 return 1e10;
64 }
65
66 double volume = molgroup->box.volume();
67 if ( volume < 1 ) {
68 molgroup->box = molgroup->max;
69 molgroup->box[0] += 1.7;
70 molgroup->box[1] += 1.7;
71 molgroup->box[2] += 1.7;
72 volume = molgroup->box.volume();
73 }
74
75 if ( verbose ) {
76 cout << "Molecular dynamics using the leapfrog integrator:" << endl;
77 cout << "Periodic box: " << molgroup->box << " " << volume << " A3" << endl;
78 cout << "Maximum iterations: " << max_iter << endl;
79 cout << "Time step: " << timestep << endl;
80 cout << "Kfriction: " << Kfriction << endl;
81 cout << "Kbond: " << md->Kbond << endl;
82 cout << "Kangle: " << md->Kangle << endl;
83 cout << "Kelectrostatic: " << md->Kelec << endl;
84 cout << "KVanderWaals: " << md->Kvdw << endl;
85 cout << "Non-bonded cutoff distance: " << md->cutoff << " A" << endl;
86
87 cout << endl << "Cycle\tEbond\tEangle\tEelec\tEvdw\tEpoint\tEnergy\tdE\tEkin" << endl;
88 }
89
90 // while ( cycle < max_iter && fabs(dE) > 1e-37 ) {
91 while ( cycle < max_iter && isfinite(E) ) {
92
93 dE = E; // Save the old energy value
94 // Initialize for the new energy values
95 E = md->Ebond = md->Eangle = md->Eelec = md->Evdw = md->Ekin = md->Epoint = 0;
96
97 // Zero the force on each atom
98 md_zero_forces(molgroup);
99
100 // Bond forces
101 md->Ebond = md_bond_forces(molgroup, md->Kbond, md->wrap);
102
103 // Angle forces
104 md->Eangle = md_angular_forces(molgroup, md->Kangle, md->wrap);
105
106 // Nonbonded forces
107 md_nonbonded_forces(molgroup, md);
108
109 md->Epoint = md_point_force(molgroup, md->point, md->Kpoint, md->pointdecay);
110
111 // Calculate the total potential energy
112 E = md->Ebond + md->Eangle + md->Eelec + md->Evdw + md->Epoint;
113 dE = E - dE; // Get the change in potential energy for this cycle
114
115 if ( dE <= 0 ) Kfriction = md->Kfriction;
116 else Kfriction = md->Kfriction*exp(-dE);
117
118 // Calculate new atomic coordinates using the leapfrog method and the kinetic energy
119 for ( mol = molgroup->mol; mol; mol = mol->next ) {
120 for( res = mol->res; res; res = res->next ) {
121 for ( atom = res->atom; atom; atom = atom->next ) {
122 atom->vel += atom->F * (timestep/atom->mass);
123 atom->vel *= Kfriction;
124 atom->vel = vector3_scalar_range(atom->vel, minvel, maxvel);
125 atom->coord += atom->vel * timestep;
126 if ( md->wrap ) atom->coord = vector3_set_PBC(atom->coord, molgroup->box);
127 vel = atom->vel.length();
128 md->Ekin += 0.5*atom->mass*vel*vel;
129 }
130 }
131 }
132
133 // Show the current energies
134 cycle++;
135
136 if ( verbose )
137 cout << cycle << tab << md->Ebond << tab << md->Eangle << tab <<
138 md->Eelec << tab << md->Evdw << tab << md->Epoint << tab <<
139 E << tab << dE << tab << md->Ekin << endl;
140 else
141 cout << cycle << tab << E << endl;
142
143 if ( !isfinite(E) ) {
144 cerr << endl << "***** Warning: The system exploded!!! *****" << endl << endl;
145 return E;
146 }
147
148 }
149
150 if ( verbose )
151 cout << endl;
152
153 return E;
154 }
155
161 int md_zero_forces(Bmolgroup* molgroup)
162 {
163 Bmolecule* mol;
164 Bresidue* res;
165 Batom* atom;
166
167 for ( mol = molgroup->mol; mol; mol = mol->next )
168 for( res = mol->res; res; res = res->next )
169 for ( atom = res->atom; atom->next; atom = atom->next )
170 atom->F = 0;
171
172 return 0;
173 }
174
190 double md_bond_forces(Bmolgroup* molgroup, double Kbond, int wrap)
191 {
192 if ( Kbond <= 0 ) return 0;
193
194 double dist, dev, fac, energy(0);
195 Vector3<double> d, Force;
196 Bbond* bond;
197 Bbond* bondlist = molgroup->bond;
198
199 for ( bond = bondlist; bond; bond = bond->next ) {
200 if ( wrap )
201 d = vector3_difference_PBC(bond->atom1->coord, bond->atom2->coord, molgroup->box);
202 else
203 d = bond->atom1->coord - bond->atom2->coord;
204 dist = d.length();
205 dev = dist - bond->l;
206 energy += Kbond*dev*dev;
207 fac = -2*Kbond*dev/dist;
208 Force = d * fac;
209 bond->atom1->F += Force;
210 bond->atom2->F -= Force;
211 }
212
213 return energy;
214 }
215
233 double md_angular_forces(Bmolgroup* molgroup, double Kangle, int wrap)
234 {
235 if ( Kangle <= 0 ) return 0;
236
237 double d1len2, d2len2, dot, fac, dcosa, c11, c12, c22, energy(0);
238 Vector3<double> d1, d2, Force;
239 Bangle* angle;
240
241 for ( angle = molgroup->angle; angle; angle = angle->next ) {
242 if ( wrap ) {
243 d1 = vector3_difference_PBC(angle->atom2->coord, angle->atom1->coord, molgroup->box);
244 d2 = vector3_difference_PBC(angle->atom2->coord, angle->atom3->coord, molgroup->box);
245 } else {
246 d1 = angle->atom2->coord - angle->atom1->coord;
247 d2 = angle->atom2->coord - angle->atom3->coord;
248 }
249 d1len2 = d1.length2();
250 d2len2 = d2.length2();
251 dot = d1.scalar(d2);
252 fac = 1/sqrt(d1len2*d2len2);
253 dcosa = cos(angle->a) - dot*fac;
254 energy += Kangle*dcosa*dcosa;
255 c12 = 2*Kangle*fac*dcosa;
256 c11 = c12*dot/d1len2;
257 c22 = c12*dot/d2len2;
258 Force = (d1 * c11) - (d2 * c12);
259 angle->atom1->F += Force;
260 Force = (d2 * c22) - (d1 * c12);
261 angle->atom3->F += Force;
262 }
263
264 return energy;
265 }
266
283 double md_nonbonded_forces(Bmolgroup* molgroup, Bmd* md)
284 {
285 if ( md->Kvdw < 0 ) md->Kvdw = 0;
286 if ( md->Kelec < 0 ) md->Kelec = 0;
287 if ( md->Kvdw <= 0 && md->Kelec <= 0 ) return 0;
288
289 int dononbond;
290 long i, ii, x, y, z, xx, yy, zz, ix, iy, iz;
291 Vector3<double> box = molgroup->box;
292 Vector3<double> sampling(md->cutoff, md->cutoff, md->cutoff);
293 Vector3<int> size((int) (box[0]/sampling[0] + 0.001),
294 (int) (box[1]/sampling[1] + 0.001), (int) (box[2]/sampling[2] + 0.001));
295 size = size.max(1);
296 for ( i=0; i<3; i++ ) sampling[i] = box[i]/size[i] + 0.001;
297 long boxsize = (long) size.volume();
298 Latom *latom, *latom2;
299
300 Latom** alist = molgroup_atom_mesh_lists(molgroup, size, sampling);
301
302 md->Evdw = md->Eelec = 0;
303
304 for ( z=0; z<size[2]; z++ ) {
305 for ( y=0; y<size[1]; y++ ) {
306 for ( x=0; x<size[0]; x++ ) {
307 i = (z*size[1] + y)*size[0] + x;
308 for ( latom = alist[i]; latom; latom = latom->next ) {
309 for ( zz=z-1; zz<=z+1; zz++ ) {
310 iz = zz;
311 if ( iz < 0 ) iz += size[2];
312 if ( iz >= size[2]) iz -= size[2];
313 for ( yy=y-1; yy<=y+1; yy++ ) {
314 iy = yy;
315 if ( iy < 0 ) iy += size[1];
316 if ( iy >= size[1] ) iy -= size[1];
317 for ( xx=x-1; xx<=x+1; xx++ ) {
318 ix = xx;
319 if ( ix < 0 ) ix += size[0];
320 if ( ix >= size[0] ) ix -= size[0];
321 ii = (iz*size[1] + iy)*size[0] + ix;
322 for ( latom2 = alist[ii]; latom2; latom2 = latom2->next ) {
323 dononbond = 1;
324 if ( latom2->atom == latom->atom ) dononbond = 0; // Same atom
325 else if ( latom2->atom->next == latom->atom ) dononbond = 0; // Bonded atoms
326 else if ( latom2->atom == latom->atom->next ) dononbond = 0; // Bonded atoms
327 else if ( latom2->atom->next ) { // Atom 2 bonds away
328 if ( latom2->atom->next->next == latom->atom ) dononbond = 0;
329 } else if ( latom->atom->next ) { // Atom 2 bonds away
330 if ( latom2->atom == latom->atom->next->next ) dononbond = 0;
331 }
332 if ( dononbond ) {
333 atom_nonbonded_forces(latom->atom, latom2->atom, md, box);
334 }
335 }
336 }
337 }
338 }
339 }
340 }
341 }
342 }
343
344 for ( i=0; i<boxsize; i++ ) kill_list((char *) alist[i], sizeof(Latom));
345 delete[] alist;
346
347 return md->Eelec+md->Evdw;
348 }
349
368 int atom_nonbonded_forces(Batom* atom, Batom* atom2, Bmd* md, Vector3<double> box)
369 {
370 if ( md->Kvdw < 0 ) md->Kvdw = 0;
371 if ( md->Kelec < 0 ) md->Kelec = 0;
372 if ( md->Kvdw <= 0 && md->Kelec <= 0 ) return 0;
373
374 Vector3<double> d, Force;
375 double rd2, rd6, rd12, dist2, invdist2, fac;
376 Bbondtype* bt = NULL;
377
378 if ( md->wrap )
379 d = vector3_difference_PBC(atom2->coord, atom->coord, box);
380 else
381 d = atom2->coord - atom->coord;
382 dist2 = d.length2();
383 if ( dist2 < md->cutoff*md->cutoff ) {
384 invdist2 = 1/dist2;
385 if ( md->Kvdw ) {
386 bt = md_find_bond_type(atom, atom2, md->bond);
387 if ( bt && bt->vdwdist > 0 ) {
388 rd2 = bt->vdwdist*bt->vdwdist*invdist2;
389 rd6 = rd2*rd2*rd2;
390 rd12 = rd6*rd6;
391 md->Evdw += md->Kvdw*(md->VdWcoeff1*rd12 - md->VdWcoeff2*rd6);
392 fac = -md->Kvdw*(rd12 - rd6)*invdist2;
393 Force = d * fac;
394 atom->F += Force;
395 }
396 }
397 if ( md->Kelec ) {
398 fac = md->Kelec*atom->chrg*atom2->chrg*sqrt(invdist2);
399 md->Eelec += fac;
400 fac *= invdist2;
401 Force = d * fac;
402 atom->F += Force;
403 }
404 }
405
406 return 0;
407 }
408
428 double md_point_force(Bmolgroup* molgroup, Vector3<double> point, double Kpoint, double decay)
429 {
430 if ( Kpoint <= 0 ) return 0;
431
432 double dist, en1, energy = 0;
433 Vector3<double> dir;
434 Bmolecule* mol;
435 Bresidue* res;
436 Batom* atom;
437
438 for ( mol = molgroup->mol; mol; mol = mol->next ) {
439 for( res = mol->res; res; res = res->next ) {
440 for ( atom = res->atom; atom; atom = atom->next ) {
441 dir = atom->coord - point;
442 dist = dir.length();
443 en1 = Kpoint*exp(-decay*dist);
444 energy += en1;
445 atom->F += dir * (decay*en1/dist);
446 }
447 }
448 }
449
450 return energy;
451 }
Bmolgroup::angle
Bangle * angle
Definition: rwmolecule.h:191
Bmolgroup::mol
Bmolecule * mol
Definition: rwmolecule.h:189
Latom::next
Latom * next
Definition: mol_util.h:22
Bmd::point
Vector3< float > point
Definition: rwmd.h:82
random_seed
long random_seed()
Gets a random seed and sets the flag.
Definition: random_numbers.cpp:41
molgroup_atom_mesh_lists
Latom ** molgroup_atom_mesh_lists(Bmolgroup *molgroup, Vector3< int > size, Vector3< double > sampling)
Generates lists of atoms based on a grid.
Definition: mol_util.cpp:882
Vector3::length
double length()
Definition: Vector3.h:222
Batom::F
Vector3< double > F
Definition: rwmolecule.h:36
Latom
Definition: mol_util.h:21
vector3_set_PBC
Vector3< T1 > vector3_set_PBC(Vector3< T1 > coord, Vector3< T2 > box)
Definition: Vector3.h:682
Bmd::Epoint
double Epoint
Definition: rwmd.h:78
Latom::atom
Batom * atom
Definition: mol_util.h:23
Bbondtype::vdwdist
float vdwdist
Definition: rwmd.h:26
utilities.h
Header file for general utilities.
md_point_force
double md_point_force(Bmolgroup *molgroup, Vector3< double > point, double Kpoint, double decay)
Calculates the atomic forces and energy resulting from a single point force.
Definition: mol_md.cpp:428
Bmolecule::res
Bresidue * res
Definition: rwmolecule.h:122
kill_list
long kill_list(char *list, unsigned long size)
Frees all the items in a linked list.
Definition: linked_list.cpp:214
Bangle::next
Bangle * next
Definition: rwmolecule.h:151
Matrix.h
Generalized matrix class.
Bmd
Definition: rwmd.h:56
md_find_bond_type
Bbondtype * md_find_bond_type(Batom *atom1, Batom *atom2, Bbondtype *bondtype)
Finds the bond type.
Definition: mol_bonds.cpp:542
Bangle
Definition: rwmolecule.h:150
Bmd::Ebond
double Ebond
Definition: rwmd.h:73
Bmolgroup::box
Vector3< double > box
Definition: rwmolecule.h:184
Vector3::max
Type max()
Definition: Vector3.h:175
Bbond::atom2
Batom * atom2
Definition: rwmolecule.h:137
Bmd::Evdw
double Evdw
Definition: rwmd.h:76
md_bond_forces
double md_bond_forces(Bmolgroup *molgroup, double Kbond, int wrap)
Calculates the covalent bond length forces and energy.
Definition: mol_md.cpp:190
linked_list.h
Header file for generalized linked list functions.
Bmd::Kpoint
double Kpoint
Definition: rwmd.h:64
isfinite
bool isfinite(complex< T > &value)
verbose
int verbose
rwmolecule.h
Header file for reading reflection files.
Bmolgroup
Definition: rwmolecule.h:170
md_angular_forces
double md_angular_forces(Bmolgroup *molgroup, double Kangle, int wrap)
Calculates the covalent bond angular forces and energy.
Definition: mol_md.cpp:233
Bmd::pointdecay
double pointdecay
Definition: rwmd.h:70
Vector3::scalar
double scalar(const Vector3 &v) const
Definition: Vector3.h:247
md_nonbonded_forces
double md_nonbonded_forces(Bmolgroup *molgroup, Bmd *md)
Calculates the non-bonded forces and energy.
Definition: mol_md.cpp:283
Bmd::Kbond
double Kbond
Definition: rwmd.h:59
Bbond::l
double l
Definition: rwmolecule.h:138
Bmd::Kfriction
double Kfriction
Definition: rwmd.h:58
Bmd::Kelec
double Kelec
Definition: rwmd.h:61
vector3_difference_PBC
Vector3< T1 > vector3_difference_PBC(Vector3< T1 > &v1, Vector3< T1 > &v2, Vector3< T2 > &box)
Definition: Vector3.h:695
Bmolecule::next
Bmolecule * next
Definition: rwmolecule.h:108
Bmd::Eelec
double Eelec
Definition: rwmd.h:75
Bmolgroup::max
Vector3< double > max
Definition: rwmolecule.h:183
Bangle::atom2
Batom * atom2
Definition: rwmolecule.h:153
vector3_scalar_range
Vector3< Type > vector3_scalar_range(Vector3< Type > vec, double min, double max)
Definition: Vector3.h:652
Vector3::length2
double length2()
Definition: Vector3.h:221
Bresidue::atom
Batom * atom
Definition: rwmolecule.h:54
Bmolecule
Definition: rwmolecule.h:107
atom_nonbonded_forces
int atom_nonbonded_forces(Batom *atom, Batom *atom2, Bmd *md, Vector3< double > box)
Calculates the non-bonded forces and energy between two atoms.
Definition: mol_md.cpp:368
Bmolgroup::bond
Bbond * bond
Definition: rwmolecule.h:190
Bresidue::next
Bresidue * next
Definition: rwmolecule.h:50
Bmd::Kangle
double Kangle
Definition: rwmd.h:60
Bresidue
Definition: rwmolecule.h:49
volume
T volume(vector< T > v)
Definition: Vector3.h:545
mol_bonds.h
Header for molecular dynamics.
random_numbers.h
Header file for functions for creating random images.
Batom
Definition: rwmolecule.h:24
Bbond::atom1
Batom * atom1
Definition: rwmolecule.h:136
Bmd::wrap
int wrap
Definition: rwmd.h:72
Vector3< double >
Bmd::VdWcoeff2
double VdWcoeff2
Definition: rwmd.h:67
Bangle::a
double a
Definition: rwmolecule.h:155
Bmd::cutoff
double cutoff
Definition: rwmd.h:69
Batom::coord
Vector3< double > coord
Definition: rwmolecule.h:30
Bmd::timestep
double timestep
Definition: rwmd.h:57
Bbond
Definition: rwmolecule.h:134
Bmd::Eangle
double Eangle
Definition: rwmd.h:74
Bbond::next
Bbond * next
Definition: rwmolecule.h:135
Bmd::VdWcoeff1
double VdWcoeff1
Definition: rwmd.h:66
Bangle::atom1
Batom * atom1
Definition: rwmolecule.h:152
Bbondtype
Definition: rwmd.h:21
md_zero_forces
int md_zero_forces(Bmolgroup *molgroup)
Zero all atomic forces.
Definition: mol_md.cpp:161
Bmd::bond
Bbondtype * bond
Definition: rwmd.h:84
Batom::chrg
double chrg
Definition: rwmolecule.h:33
Bangle::atom3
Batom * atom3
Definition: rwmolecule.h:154
md_leapfrog
double md_leapfrog(Bmolgroup *molgroup, Bmd *md, int max_iter, double velocitylimit)
Molecular dynamics using the leapfrog integrator.
Definition: mol_md.cpp:38
Vector3::volume
double volume()
Definition: Vector3.h:235
Bmd::Ekin
double Ekin
Definition: rwmd.h:80
mol_md.h
Header for molecular dynamics.
Bmd::Kvdw
double Kvdw
Definition: rwmd.h:62
Batom::next
Batom * next
Definition: rwmolecule.h:25
Batom::mass
double mass
Definition: rwmolecule.h:32
Batom::vel
Vector3< double > vel
Definition: rwmolecule.h:35
error_show
int error_show(string message, string file, int line)
Displays the error with file and line reference.
Definition: utilities.cpp:755
tab
ostream & tab(ostream &out)
Definition: utilities.cpp:21