| Bsoft 2.0.5 Bernard's software package

mol_water.cpp
Go to the documentation of this file.
1
9 #include "rwmolecule.h"
10 #include "mol_bonds.h"
11 #include "Matrix3.h"
12 #include "linked_list.h"
13 #include "random_numbers.h"
14 #include "utilities.h"
15
16 // Declaration of global variables
17 extern int verbose; // Level of output to the screen
18
26 Bmolecule* mol_generate_one_water(Bmolecule** mollist, char* watername, Vector3<double> Ocoord)
27 {
28 double rand_max = 1.0*get_rand_max();
29 double OHbond = 0.9572;
30 double HOHangle = 109.47*M_PI/180.0;
31 char resname[12] = "HOH";
32 char atomname[12] = "O";
33 Vector3<double> H1vec, H2vec;
34 Matrix3 mat(1);
35
36 Bmolecule* mol = molecule_add(mollist, watername);
37 Bresidue* res = residue_add(&mol->res, resname);
38 res->num = 1;
39
40 strcpy(atomname, "O");
41 Batom* atom = atom_add(&res->atom, atomname);
42 atom->el[0] = 'O';
43 atom->num = 1;
44 atom->mass = 16;
45 atom->chrg = -0.834;
46 atom->coord = Ocoord;
47
48 strcpy(atomname, "HO1");
49 atom = atom_add(&atom, atomname);
50 atom->el[0] = 'H';
51 atom->num = 2;
52 atom->mass = 1;
53 atom->chrg = 0.417;
54 H1vec[0] = random()/rand_max - 0.5;
55 H1vec[1] = random()/rand_max - 0.5;
56 H1vec[2] = random()/rand_max - 0.5;
57 H1vec.normalize();
58 atom->coord = (H1vec * OHbond) + Ocoord;
59
60 strcpy(atomname, "HO2");
61 atom = atom_add(&atom, atomname);
62 atom->el[0] = 'H';
63 atom->num = 3;
64 atom->mass = 1;
65 atom->chrg = 0.417;
66 H2vec[0] = random()/rand_max - 0.5;
67 H2vec[1] = random()/rand_max - 0.5;
68 H2vec[2] = random()/rand_max - 0.5;
69 H2vec.normalize();
70
71 H2vec = H1vec.cross(H2vec);
72 mat = Matrix3(H2vec, HOHangle);
73 H2vec = mat * H1vec;
74 atom->coord = (H2vec * OHbond) + Ocoord;
75
76 return mol;
77 }
78
89 Bmolgroup* molgroup_generate_regular_water(Vector3<double> size, int type)
90 {
91 if ( size.volume() < 1 ) {
92 cerr << "Error: A box size must be specified!" << endl;
93 return NULL;
94 }
95
96 Bmolgroup* molgroup = molgroup_init();
97
98 char c = 65; // Character for molecule ID
99 // double rand_max = 1.0*get_rand_max();
100 double x, y, z;
101
102 Vector3<double> Ocoord, start;
103 Vector3<double> interval(3.1, 3.1, 3.1); // Interval between water molecules in each direction
104 if ( type == 3 ) {
105 interval[0] = 3.48;
106 interval[1] = interval[0]*sqrt(3.0)/2.0;
107 interval[2] = interval[0]*sqrt(2.0/3.0);
108 }
109
110 size[0] = interval[0]*((int) (size[0]/interval[0])) + 0.001;
111 size[1] = interval[1]*((int) (size[1]/interval[1])) + 0.001;
112 size[2] = interval[2]*((int) (size[2]/interval[2])) + 0.001;
113
114 double volume = size.volume();
115 long n = (long) (volume*0.03346);
116
117 Bmolecule* mol = NULL;
118
119 char watername[20] = "A";
120
121 if ( verbose & ( VERB_LABEL | VERB_PROCESS ) )
122 cout << "Generating regular water" << endl;
123
124 if ( verbose & VERB_PROCESS ) {
125 cout << "Volume: " << size << " = " << volume << " A3" << endl;
126 cout << "Interval between molecules: " << interval << " A" << endl;
127 cout << "Estimated number of waters: " << n << endl << endl;
128 }
129
130 if ( molgroup->mol ) for ( mol = molgroup->mol; mol->next; mol = mol->next ) ;
131
132 n = 0;
133 for ( z=interval[2]/2; z<size[2]; z+=interval[2] ) {
134 if ( type == 3 ) start[1] = 1 - start[1];
135 start[0] = start[1];
136 for ( y=interval[1]/2+start[1]*interval[0]/(2*sqrt(3.0)); y<size[1]; y+=interval[1] ) {
137 if ( type == 3 ) start[0] = 1 - start[0];
138 for ( x=(2-start[0])*interval[0]/2; x<size[0]; x+=interval[0] ) {
139 watername[0] = c;
140 Ocoord[0] = x;
141 Ocoord[1] = y;
142 Ocoord[2] = z;
143 mol = mol_generate_one_water(&mol, watername, Ocoord);
144 if ( !molgroup->mol ) molgroup->mol = mol;
145 n++;
146 c++;
147 if ( c > 90 ) c = 65;
148 }
149 }
150 }
151
152 molgroup_stats(molgroup);
153
154 molgroup->box[0] = molgroup->max[0] + interval[0]/2;
155 molgroup->box[1] = molgroup->max[1] + interval[1]/2;
156 molgroup->box[2] = molgroup->max[2] + interval[2]/2;
157
158 molgroup->box = size;
159
160 volume = molgroup->box.volume();
161
162 if ( verbose & VERB_PROCESS ) {
163 cout << "Number of waters: " << n << endl;
164 cout << "Volume: " << molgroup->box << " = " << volume << " A3" << endl;
165 cout << "Density: " << n*1.0/volume <<
166 " molecules/A3 (" << n/(volume*0.03346) << ")" << endl << endl;
167 }
168
169 return molgroup;
170 }
171
181 Bmolgroup* molgroup_generate_random_water(Vector3<double> size)
182 {
183 if ( size.volume() < 1 ) {
184 cerr << "Error: A box size must be specified!" << endl;
185 return NULL;
186 }
187
188 random_seed();
189
190 int i;
191 char c = 65; // Character for molecule ID
192 double rand_max = 1.0*get_rand_max();
193
194 double volume = size.volume();
195 long n = (long) (volume*0.03346);
196 Vector3<double> Ocoord;
197
198 Bmolecule* mol = NULL;
199 Batom* atom;
200
201 char watername[20] = "A";
202
203 if ( verbose & ( VERB_LABEL | VERB_PROCESS ) )
204 cout << "Generating random water" << endl;
205
206 if ( verbose & VERB_PROCESS ) {
207 cout << "Volume: " << size << " = " << volume << " A3" << endl;
208 cout << "Number of waters: " << n << endl << endl;
209 }
210
211 Bmolgroup* molgroup = molgroup_init();
212
213 if ( molgroup->mol ) for ( mol = molgroup->mol; mol->next; mol = mol->next ) ;
214
215 for ( i=0; i<n; i++ ) {
216 watername[0] = c;
217 Ocoord[0] = size[0]*random()/rand_max;
218 Ocoord[1] = size[1]*random()/rand_max;
219 Ocoord[2] = size[2]*random()/rand_max;
220 mol = mol_generate_one_water(&mol, watername, Ocoord);
221 if ( !molgroup->mol ) molgroup->mol = mol;
222 for ( atom = mol->res->atom; atom; atom = atom->next )
223 atom->coord = vector3_set_PBC(atom->coord, size);
224 c++;
225 if ( c > 90 ) c = 65;
226 }
227
228 molgroup_stats(molgroup);
229
230 molgroup->box = size;
231
232 volume = molgroup->box.volume();
233
234 if ( verbose & VERB_PROCESS ) {
235 cout << "Number of waters: " << n << endl;
236 cout << "Volume: " << molgroup->box << " = " << volume << " A3" << endl;
237 cout << "Density: " << n*1.0/volume <<
238 " molecules/A3 (" << n/(volume*0.03346) << ")" << endl << endl;
239 }
240
241 return molgroup;
242 }
243
249 Bbond* water_bond_list(Bmolgroup* molgroup)
250 {
251 // if ( molgroup->bond ) {
252 // cerr << "Warning: Bond list already defined!" << endl;
253 // return molgroup->bond;
254 // }
255
256 if ( molgroup->bond ) {
257 if ( verbose ) cerr << "Warning: Deleting original bond list!" << endl;
258 bond_kill(molgroup->bond);
259 }
260
261 Bmolecule* mol;
262 Bresidue* res;
263 Batom* atom;
264 Bbond* bondlist = NULL;
265 Bbond* bond = NULL;
266 double OHbond = 0.9572;
267 int nbond = 0;
268
269 for ( nbond = 0, mol = molgroup->mol; mol; mol = mol->next ) {
270 res = mol->res;
271 atom = res->atom;
272 if ( bond ) bond = bond_add(&bond, atom, atom->next, OHbond, 1);
273 else bond = bond_add(&bondlist, atom, atom->next, OHbond, 1);
274 bond = bond_add(&bond, atom, atom->next->next, OHbond, 1);
275 nbond += 2;
276 }
277
278 if ( verbose & VERB_PROCESS )
279 cout << "Number of bonds generated: " << nbond << endl;
280
281 molgroup->bond = bondlist;
282
283 return bondlist;
284 }
285
291 Bangle* water_angle_list(Bmolgroup* molgroup)
292 {
293 Bmolecule* mol;
294 Bresidue* res;
295 Batom* atom;
296 Bangle* angle = NULL;
297 double OHangle = 109.47*M_PI/180.0;
298 int nangle = 0;
299
300 molgroup->angle = NULL;
301
302 for ( nangle = 0, mol = molgroup->mol; mol; mol = mol->next ) {
303 res = mol->res;
304 atom = res->atom;
305 angle = angle_add(&angle, atom->next, atom, atom->next->next, OHangle, 1);
306 if ( !molgroup->angle ) molgroup->angle = angle;
307 nangle ++;
308 }
309
310 if ( verbose & VERB_PROCESS )
311 cout << "Number of angles generated: " << nangle << endl;
312
313 return molgroup->angle;
314 }
315
323 int molgroup_calc_water_rdf(Bmolgroup* molgroup, double interval, double cutoff)
324 {
325 int i, ii, j, t, x, y, z, xx, yy, zz, ix, iy, iz;
326 Vector3<double> box = molgroup->box;
327 double dist;
328 Vector3<double> d, sampling(cutoff, cutoff, cutoff);
329 Vector3<int> size((int) (box[0]/sampling[0] + 0.001),
330 (int) (box[1]/sampling[1] + 0.001), (int) (box[2]/sampling[2] + 0.001));
331 size = size.max(1);
332 for ( i=0; i<3; i++ ) sampling[i] = box[i]/size[i] + 0.001;
333
334 Bmolecule* mol;
335 Bresidue* res;
336
337 Latom** alist = molgroup_atom_mesh_lists(molgroup, size, sampling);
338 Latom *latom, *latom2;
339
340 double mult = 1.0/interval;
341 int n = (int) (mult*cutoff);
342 int* rdf = new int[n*3];
343 for ( i=0; i<n*3; i++ ) rdf[i] = 0;
344
345 for ( i=z=0; z<size[2]; z++ ) {
346 for ( y=0; y<size[1]; y++ ) {
347 for ( x=0; x<size[0]; x++, i++ ) {
348 for ( latom = alist[i]; latom; latom = latom->next ) {
349 for ( zz=z-1; zz<=z+1; zz++ ) {
350 iz = zz;
351 if ( iz < 0 ) iz += size[2];
352 if ( iz >= size[2]) iz -= size[2];
353 for ( yy=y-1; yy<=y+1; yy++ ) {
354 iy = yy;
355 if ( iy < 0 ) iy += size[1];
356 if ( iy >= size[1] ) iy -= size[1];
357 for ( xx=x-1; xx<=x+1; xx++ ) {
358 ix = xx;
359 if ( ix < 0 ) ix += size[0];
360 if ( ix >= size[0] ) ix -= size[0];
361 ii = (iz*size[1] + iy)*size[0] + ix;
362 for ( latom2 = alist[ii]; latom2; latom2 = latom2->next )
363 if ( latom2->atom != latom->atom ) {
364 d = vector3_difference_PBC(latom2->atom->coord, latom->atom->coord, box);
365 dist = d.length();
366 if ( dist < cutoff ) {
367 j = (int) (mult*dist + 0.5);
368 if ( j < n ) {
369 if ( latom->atom->el[0] == 'H' && latom2->atom->el[0] == 'H' ) t = 0;
370 else if ( latom->atom->el[0] == 'H' || latom2->atom->el[0] == 'H' ) t = 1;
371 else t = 2;
372 rdf[3*j+t] += 1;
373 }
374 }
375 }
376 }
377 }
378 }
379 }
380 }
381 }
382 }
383
384 for ( i=0; i<size.volume(); i++ ) kill_list((char *) alist[i], sizeof(Latom));
385 delete[] alist;
386
387 int nwater = 0;
388 for ( nwater = 0, mol = molgroup->mol; mol; mol = mol->next )
389 for ( res = mol->res; res; res = res->next ) nwater++;
390
391 cout << "Calculating the radial distribution function:" << endl;
392
393 double vol_per_water = 180/6.022; // Volume occupied by water = 29.9 A^3
394 // double vol_within_cutoff = (4.0/3.0)*M_PI*cutoff*cutoff*cutoff;
395 // double water_within_cutoff = vol_within_cutoff/vol_per_water;
396 long ndist[3] = {0,0,0};
397 double rdftot[3] = {0,0,0};
398 double norm[3], vol_surface;
399 double vol_surf_fac = (4.0/3.0)*M_PI*interval*interval*interval;
400 cout << endl << "r(A)\tH-H\tRDF(HH)\tH-O\tRDF(HO)\tO-O\tRDF(OO)" << endl;
401 for ( i=1; i<n; i++ ) {
402 cout << i*interval;
403 vol_surface = vol_surf_fac*(3*i*i + 0.25);
404 norm[2] = vol_per_water/(vol_surface*2*nwater); // Normalizer for RDF(OO)
405 norm[0] = norm[1] = 0.25*norm[2]; // Volume per H is half and 2 times more H's
406 for ( t=0; t<3; t++ ) {
407 cout << tab << rdf[3*i+t] << tab << rdf[3*i+t]*norm[t];
408 ndist[t] += rdf[3*i+t];
409 rdftot[t] += rdf[3*i+t]*norm[t];
410 }
411 cout << endl;
412 }
413 cout << "Number of distances included = " << ndist[0] << " " << ndist[1] << " " << ndist[2] << endl;
414 cout << "RDF sum = " << rdftot[0] << " " << rdftot[1] << " " << rdftot[2] << endl;
415 cout << "RDF avg = " << rdftot[0]/n << " " << rdftot[1]/n << " " << rdftot[2]/n << endl << endl;
416
417 delete[] rdf;
418
419 return 0;
420 }
421
Bmolgroup::angle
Bangle * angle
Definition: rwmolecule.h:191
Bmolgroup::mol
Bmolecule * mol
Definition: rwmolecule.h:189
Vector3::cross
Vector3 cross(const Vector3 &v)
Definition: Vector3.h:250
Latom::next
Latom * next
Definition: mol_util.h:22
Vector3::normalize
double normalize()
Definition: Vector3.h:236
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
angle_add
Bangle * angle_add(Bangle **angle, Batom *atom1, Batom *atom2, Batom *atom3, double a, double k)
Adds an angle to a linked list.
Definition: rwmolecule.cpp:312
Vector3::length
double length()
Definition: Vector3.h:222
Latom
Definition: mol_util.h:21
vector3_set_PBC
Vector3< T1 > vector3_set_PBC(Vector3< T1 > coord, Vector3< T2 > box)
Definition: Vector3.h:682
Latom::atom
Batom * atom
Definition: mol_util.h:23
utilities.h
Header file for general utilities.
molgroup_generate_regular_water
Bmolgroup * molgroup_generate_regular_water(Vector3< double > size, int type)
Generates a block of water based on a regular lattice.
Definition: mol_water.cpp:89
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
Matrix3
Definition: Matrix3.h:17
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:107
Bangle
Definition: rwmolecule.h:150
bond_add
Bbond * bond_add(Bbond **bond, Batom *atom1, Batom *atom2, double l, double k)
Adds a bond to a linked list.
Definition: rwmolecule.cpp:269
Matrix3.h
3x3 Matrix manipulation functions
residue_add
Bresidue * residue_add(Bresidue **res, const char *type)
Adds a residue to a linked list.
Definition: rwmolecule.cpp:113
Bmolgroup::box
Vector3< double > box
Definition: rwmolecule.h:184
Vector3::max
Type max()
Definition: Vector3.h:175
Batom::num
int num
Definition: rwmolecule.h:26
M_PI
#define M_PI
Definition: utilities.h:59
linked_list.h
Header file for generalized linked list functions.
water_angle_list
Bangle * water_angle_list(Bmolgroup *molgroup)
Generates a bond angle list for a block of waters.
Definition: mol_water.cpp:291
rwmolecule.h
Header file for reading reflection files.
molgroup_calc_water_rdf
int molgroup_calc_water_rdf(Bmolgroup *molgroup, double interval, double cutoff)
Calculates a radial distribution function for water molecules.
Definition: mol_water.cpp:323
Bmolgroup
Definition: rwmolecule.h:170
molgroup_stats
long molgroup_stats(Bmolgroup *molgroup, int show)
Calculates the statistics of a molecule group.
Definition: rwmolecule.cpp:1291
water_bond_list
Bbond * water_bond_list(Bmolgroup *molgroup)
Generates a bond list for a block of waters.
Definition: mol_water.cpp:249
molgroup_init
Bmolgroup * molgroup_init()
Initializes and allocates a new molecule group.
Definition: rwmolecule.cpp:45
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
molecule_add
Bmolecule * molecule_add(Bmolecule **mol, char *name)
Adds a molecule to a linked list.
Definition: rwmolecule.cpp:76
bond_kill
int bond_kill(Bbond *bond)
Dealocates a list of bonds.
Definition: rwmolecule.cpp:480
Bmolgroup::max
Vector3< double > max
Definition: rwmolecule.h:183
Bresidue::atom
Batom * atom
Definition: rwmolecule.h:54
get_rand_max
long get_rand_max()
Finds the maximum random number for a system.
Definition: random_numbers.cpp:22
Bmolecule
Definition: rwmolecule.h:107
atom_add
Batom * atom_add(Batom **atom, const char *type)
Adds an atom to a linked list.
Definition: rwmolecule.cpp:152
Bmolgroup::bond
Bbond * bond
Definition: rwmolecule.h:190
Bresidue::next
Bresidue * next
Definition: rwmolecule.h:50
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
mol_generate_one_water
Bmolecule * mol_generate_one_water(Bmolecule **mollist, char *watername, Vector3< double > Ocoord)
Generates one water molecule at a given location.
Definition: mol_water.cpp:26
Vector3< double >
Bresidue::num
int num
Definition: rwmolecule.h:51
Batom::coord
Vector3< double > coord
Definition: rwmolecule.h:30
Bbond
Definition: rwmolecule.h:134
Batom::el
char el[4]
Definition: rwmolecule.h:27
Batom::chrg
double chrg
Definition: rwmolecule.h:33
Vector3::volume
double volume()
Definition: Vector3.h:235
VERB_LABEL
#define VERB_LABEL
Definition: utilities.h:106
Batom::next
Batom * next
Definition: rwmolecule.h:25
Batom::mass
double mass
Definition: rwmolecule.h:32
tab
ostream & tab(ostream &out)
Definition: utilities.cpp:21
verbose
int verbose
molgroup_generate_random_water
Bmolgroup * molgroup_generate_random_water(Vector3< double > size)
Generates a block of water with random placement.
Definition: mol_water.cpp:181