ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/utils/sysbuilder/bilayerSys.cpp
Revision: 763
Committed: Mon Sep 15 16:52:02 2003 UTC (21 years, 7 months ago) by tim
File size: 13521 byte(s)
Log Message:
add conserved quantity to statWriter
fix bug of vector wrapping at NPTi

File Contents

# Content
1
2 #include <iostream>
3 #include <vector>
4 #include <algorithm>
5
6 #include <cstdlib>
7 #include <cstring>
8 #include <cmath>
9
10
11 #include "simError.h"
12 #include "SimInfo.hpp"
13 #include "ReadWrite.hpp"
14
15 #include "MoLocator.hpp"
16 #include "sysBuild.hpp"
17 #include "bilayerSys.hpp"
18
19 #include "latticeBuilder.hpp"
20
21 class SortCond{
22
23 public:
24 bool operator()(const pair<int, double>& p1, const pair<int, double>& p2){
25 return p1.second < p2.second;
26 }
27
28
29 };
30
31
32 void buildMap( double &x, double &y, double &z,
33 double boxX, double boxY, double boxZ );
34
35 int buildRandomBilayer( void );
36
37 void getRandomRot( double rot[3][3] );
38
39 int buildBilayer( int isRandom ){
40
41 if( isRandom ){
42 return buildRandomBilayer();
43 }
44 else{
45 sprintf( painCave.errMsg,
46 "Cannot currently create a non-random bilayer.\n" );
47 painCave.isFatal = 1;
48 simError();
49 return 0;
50 }
51 }
52
53
54 int buildRandomBilayer( void ){
55
56 typedef struct{
57 double rot[3][3];
58 double pos[3];
59 } coord;
60
61
62
63 const double waterRho = 0.0334; // number density per cubic angstrom
64 const double waterVol = 4.0 / waterRho; // volume occupied by 4 waters
65 const double waterCell = 4.929; // fcc unit cell length
66
67 Lattice myFCC( FCC_LATTICE_TYPE, waterCell );
68 double *posX, *posY, *posZ;
69 double pos[3], posA[3], posB[3];
70
71 const double water_padding = 6.0;
72 const double lipid_spaceing = 8.0;
73
74
75 int i,j,k, l, m;
76 int nAtoms, atomIndex, molIndex, molID;
77 int* molSeq;
78 int* molMap;
79 int* molStart;
80 int* cardDeck;
81 int deckSize;
82 int rSite, rCard;
83 double cell;
84 int nCells, nSites, siteIndex;
85
86 coord testSite;
87
88 Atom** atoms;
89 SimInfo* simnfo;
90 SimState* theConfig;
91 DumpWriter* writer;
92
93 MoleculeStamp* lipidStamp;
94 MoleculeStamp* waterStamp;
95 MoLocator *lipidLocate;
96 MoLocator *waterLocate;
97 int foundLipid, foundWater;
98 int nLipids, lipidNatoms, nWaters, waterNatoms;
99 double testBox, maxLength;
100
101 srand48( RAND_SEED );
102
103
104 // create the simInfo objects
105
106 simnfo = new SimInfo[3];
107
108
109 // set the the lipidStamp
110
111 foundLipid = 0;
112 foundWater = 0;
113 for(i=0; i<bsInfo.nComponents; i++){
114 if( !strcmp( bsInfo.compStamps[i]->getID(), bsInfo.lipidName ) ){
115
116 foundLipid = 1;
117 lipidStamp = bsInfo.compStamps[i];
118 nLipids = bsInfo.componentsNmol[i];
119 }
120 if( !strcmp( bsInfo.compStamps[i]->getID(), bsInfo.waterName ) ){
121
122 foundWater = 1;
123
124 waterStamp = bsInfo.compStamps[i];
125 nWaters = bsInfo.componentsNmol[i];
126 }
127 }
128 if( !foundLipid ){
129 sprintf(painCave.errMsg,
130 "Could not find lipid \"%s\" in the bass file.\n",
131 bsInfo.lipidName );
132 painCave.isFatal = 1;
133 simError();
134 }
135 if( !foundWater ){
136 sprintf(painCave.errMsg,
137 "Could not find solvent \"%s\" in the bass file.\n",
138 bsInfo.waterName );
139 painCave.isFatal = 1;
140 simError();
141 }
142
143 //create the temp Molocator and atom Arrays
144
145 lipidLocate = new MoLocator( lipidStamp );
146 lipidNatoms = lipidStamp->getNAtoms();
147 maxLength = lipidLocate->getMaxLength();
148
149 waterLocate = new MoLocator( waterStamp );
150 waterNatoms = waterStamp->getNAtoms();
151
152 nAtoms = lipidNatoms;
153
154 simnfo[0].n_atoms = nAtoms;
155 simnfo[0].atoms=new Atom*[nAtoms];
156
157 theConfig = simnfo[0].getConfiguration();
158 theConfig->createArrays( simnfo[0].n_atoms );
159
160 atoms=simnfo[0].atoms;
161
162
163 // create the test box for initial water displacement
164
165 testBox = maxLength + waterCell * 4.0; // pad with 4 cells
166 nCells = (int)( testBox / waterCell + 1.0 );
167 int testWaters = 4 * nCells * nCells * nCells;
168
169 double* waterX = new double[testWaters];
170 double* waterY = new double[testWaters];
171 double* waterZ = new double[testWaters];
172
173 double x0 = 0.0 - ( testBox * 0.5 );
174 double y0 = 0.0 - ( testBox * 0.5 );
175 double z0 = 0.0 - ( testBox * 0.5 );
176
177
178 // create an fcc lattice in the water box.
179
180 int ndx = 0;
181 for( i=0; i < nCells; i++ ){
182 for( j=0; j < nCells; j++ ){
183 for( k=0; k < nCells; k++ ){
184
185 myFCC.getLatticePoints(&posX, &posY, &posZ, i, j, k);
186 for(l=0; l<4; l++){
187 waterX[ndx]=posX[l];
188 waterY[ndx]=posY[l];
189 waterZ[ndx]=posZ[l];
190 ndx++;
191 }
192 }
193 }
194 }
195
196 // calculate the number of water's displaced by our lipid.
197
198 testSite.rot[0][0] = 1.0;
199 testSite.rot[0][1] = 0.0;
200 testSite.rot[0][2] = 0.0;
201
202 testSite.rot[1][0] = 0.0;
203 testSite.rot[1][1] = 1.0;
204 testSite.rot[1][2] = 0.0;
205
206 testSite.rot[2][0] = 0.0;
207 testSite.rot[2][1] = 0.0;
208 testSite.rot[2][2] = 1.0;
209
210 testSite.pos[0] = 0.0;
211 testSite.pos[1] = 0.0;
212 testSite.pos[2] = 0.0;
213
214 lipidLocate->placeMol( testSite.pos, testSite.rot, atoms, 0, theConfig );
215
216 int *isActive = new int[testWaters];
217 for(i=0; i<testWaters; i++) isActive[i] = 1;
218
219 int n_deleted = 0;
220 double dx, dy, dz;
221 double dx2, dy2, dz2, dSqr;
222 double rCutSqr = water_padding * water_padding;
223
224 for(i=0; ( (i<testWaters) && isActive[i] ); i++){
225 for(j=0; ( (j<lipidNatoms) && isActive[i] ); j++){
226
227 atoms[j]->getPos( pos );
228
229 dx = waterX[i] - pos[0];
230 dy = waterY[i] - pos[1];
231 dz = waterZ[i] - pos[2];
232
233 buildMap( dx, dy, dz, testBox, testBox, testBox );
234
235 dx2 = dx * dx;
236 dy2 = dy * dy;
237 dz2 = dz * dz;
238
239 dSqr = dx2 + dy2 + dz2;
240 if( dSqr < rCutSqr ){
241 isActive[i] = 0;
242 n_deleted++;
243 }
244 }
245 }
246
247 int targetWaters = nWaters + n_deleted * nLipids;
248
249 targetWaters = (int) ( targetWaters * 1.2 );
250
251 // find the best box size for the sim
252
253 int nCellsX, nCellsY, nCellsZ;
254
255 const double boxTargetX = 66.22752;
256 const double boxTargetY = 60.53088;
257
258 nCellsX = (int)ceil(boxTargetX / waterCell);
259 nCellsY = (int)ceil(boxTargetY / waterCell);
260
261 int testTot;
262 int done = 0;
263 nCellsZ = 0;
264 while( !done ){
265
266 nCellsZ++;
267 testTot = 4 * nCellsX * nCellsY * nCellsZ;
268
269 if( testTot >= targetWaters ) done = 1;
270 }
271
272 // create the new water box to the new specifications
273
274 int newWaters = nCellsX * nCellsY * nCellsZ * 4;
275
276 delete[] waterX;
277 delete[] waterY;
278 delete[] waterZ;
279
280 coord* waterSites = new coord[newWaters];
281
282 double box_x = waterCell * nCellsX;
283 double box_y = waterCell * nCellsY;
284 double box_z = waterCell * nCellsZ;
285
286 // create an fcc lattice in the water box.
287
288 ndx = 0;
289 for( i=0; i < nCellsX; i++ ){
290 for( j=0; j < nCellsY; j++ ){
291 for( k=0; k < nCellsZ; k++ ){
292
293 myFCC.getLatticePoints(&posX, &posY, &posZ, i, j, k);
294 for(l=0; l<4; l++){
295 waterSites[ndx].pos[0] = posX[l];
296 waterSites[ndx].pos[1] = posY[l];
297 waterSites[ndx].pos[2] = posZ[l];
298 ndx++;
299 }
300 }
301 }
302 }
303
304 coord* lipidSites = new coord[nLipids];
305
306 // start a 3D RSA for the for the lipid placements
307
308
309 int reject;
310 int testDX, acceptedDX;
311
312 nAtoms = nLipids * lipidNatoms;
313
314 simnfo[1].n_atoms = nAtoms;
315 simnfo[1].atoms=new Atom*[nAtoms];
316
317 theConfig = simnfo[1].getConfiguration();
318 theConfig->createArrays( simnfo[1].n_atoms );
319
320 atoms=simnfo[1].atoms;
321
322 rCutSqr = lipid_spaceing * lipid_spaceing;
323
324 for(i=0; i<nLipids; i++ ){
325 done = 0;
326 while( !done ){
327
328 lipidSites[i].pos[0] = drand48() * box_x;
329 lipidSites[i].pos[1] = drand48() * box_y;
330 lipidSites[i].pos[2] = drand48() * box_z;
331
332 getRandomRot( lipidSites[i].rot );
333
334 ndx = i * lipidNatoms;
335
336 lipidLocate->placeMol( lipidSites[i].pos, lipidSites[i].rot, atoms,
337 ndx, theConfig );
338
339 reject = 0;
340 for( j=0; !reject && j<i; j++){
341 for(k=0; !reject && k<lipidNatoms; k++){
342
343 acceptedDX = j*lipidNatoms + k;
344 for(l=0; !reject && l<lipidNatoms; l++){
345
346 testDX = ndx + l;
347
348 atoms[testDX]->getPos( posA );
349 atoms[acceptedDX]->getPos( posB );
350
351 dx = posA[0] - posB[0];
352 dy = posA[1] - posB[1];
353 dz = posA[2] - posB[2];
354
355 buildMap( dx, dy, dz, box_x, box_y, box_z );
356
357 dx2 = dx * dx;
358 dy2 = dy * dy;
359 dz2 = dz * dz;
360
361 dSqr = dx2 + dy2 + dz2;
362 if( dSqr < rCutSqr ) reject = 1;
363 }
364 }
365 }
366
367 if( reject ){
368
369 for(j=0; j< lipidNatoms; j++) delete atoms[ndx+j];
370 }
371 else{
372 done = 1;
373 std::cout << (i+1) << " has been accepted\n";
374 }
375 }
376 }
377
378
379 // zSort of the lipid positions
380
381
382 vector< pair<int,double> >zSortArray;
383 for(i=0;i<nLipids;i++)
384 zSortArray.push_back( make_pair(i, lipidSites[i].pos[2]) );
385
386 sort(zSortArray.begin(),zSortArray.end(),SortCond());
387
388 ofstream outFile( "./zipper.bass", ios::app);
389
390 for(i=0; i<nLipids; i++){
391 outFile << "zConstraint[" << i << "]{\n"
392 << " molIndex = " << zSortArray[i].first << ";\n"
393 << " zPos = ";
394
395 if(i<32) outFile << "60.0;\n";
396 else outFile << "100.0;\n";
397
398 outFile << " kRatio = 0.5;\n"
399 << "}\n";
400 }
401
402 outFile.close();
403
404
405 // cut out the waters that overlap with the lipids.
406
407
408 delete[] isActive;
409 isActive = new int[newWaters];
410 for(i=0; i<newWaters; i++) isActive[i] = 1;
411 int n_active = newWaters;
412 rCutSqr = water_padding * water_padding;
413
414 for(i=0; ( (i<newWaters) && isActive[i] ); i++){
415 for(j=0; ( (j<nAtoms) && isActive[i] ); j++){
416
417 atoms[j]->getPos( pos );
418
419 dx = waterSites[i].pos[0] - pos[0];
420 dy = waterSites[i].pos[1] - pos[1];
421 dz = waterSites[i].pos[2] - pos[2];
422
423 buildMap( dx, dy, dz, box_x, box_y, box_z );
424
425 dx2 = dx * dx;
426 dy2 = dy * dy;
427 dz2 = dz * dz;
428
429 dSqr = dx2 + dy2 + dz2;
430 if( dSqr < rCutSqr ){
431 isActive[i] = 0;
432 n_active--;
433
434
435 }
436 }
437 }
438
439
440
441
442 if( n_active < nWaters ){
443
444 sprintf( painCave.errMsg,
445 "Too many waters were removed, edit code and try again.\n" );
446
447 painCave.isFatal = 1;
448 simError();
449 }
450
451 int quickKill;
452 while( n_active > nWaters ){
453
454 quickKill = (int)(drand48()*newWaters);
455
456 if( isActive[quickKill] ){
457 isActive[quickKill] = 0;
458 n_active--;
459
460 }
461 }
462
463 if( n_active != nWaters ){
464
465 sprintf( painCave.errMsg,
466 "QuickKill didn't work right. n_active = %d, and nWaters = %d\n",
467 n_active, nWaters );
468 painCave.isFatal = 1;
469 simError();
470 }
471
472 // clean up our messes before building the final system.
473
474 simnfo[0].getConfiguration()->destroyArrays();
475 simnfo[1].getConfiguration()->destroyArrays();
476
477 // create the real Atom arrays
478
479 nAtoms = 0;
480 molIndex = 0;
481 molStart = new int[nLipids + nWaters];
482
483 for(j=0; j<nLipids; j++){
484 molStart[molIndex] = nAtoms;
485 molIndex++;
486 nAtoms += lipidNatoms;
487 }
488
489 for(j=0; j<nWaters; j++){
490 molStart[molIndex] = nAtoms;
491 molIndex++;
492 nAtoms += waterNatoms;
493 }
494
495 theConfig = simnfo[2].getConfiguration();
496 theConfig->createArrays( nAtoms );
497 simnfo[2].atoms = new Atom*[nAtoms];
498 atoms = simnfo[2].atoms;
499 simnfo[2].n_atoms = nAtoms;
500
501 // initialize lipid positions
502
503 molIndex = 0;
504 for(i=0; i<nLipids; i++ ){
505 lipidLocate->placeMol( lipidSites[i].pos, lipidSites[i].rot, atoms,
506 molStart[molIndex], theConfig );
507 molIndex++;
508 }
509
510 // initialize the water positions
511
512 for(i=0; i<newWaters; i++){
513
514 if( isActive[i] ){
515
516 getRandomRot( waterSites[i].rot );
517 waterLocate->placeMol( waterSites[i].pos, waterSites[i].rot, atoms,
518 molStart[molIndex], theConfig );
519 molIndex++;
520 }
521 }
522
523 // set up the SimInfo object
524
525 double Hmat[3][3];
526
527 Hmat[0][0] = box_x;
528 Hmat[0][1] = 0.0;
529 Hmat[0][2] = 0.0;
530
531 Hmat[1][0] = 0.0;
532 Hmat[1][1] = box_y;
533 Hmat[1][2] = 0.0;
534
535 Hmat[2][0] = 0.0;
536 Hmat[2][1] = 0.0;
537 Hmat[2][2] = box_z;
538
539
540 bsInfo.boxX = box_x;
541 bsInfo.boxY = box_y;
542 bsInfo.boxZ = box_z;
543
544 simnfo[2].setBoxM( Hmat );
545
546 sprintf( simnfo[2].sampleName, "%s.dump", bsInfo.outPrefix );
547 sprintf( simnfo[2].finalName, "%s.init", bsInfo.outPrefix );
548
549 // set up the writer and write out
550
551 writer = new DumpWriter( &simnfo[2] );
552 writer->writeFinal( 0.0 );
553
554 // clean up the memory
555
556 // if( molMap != NULL ) delete[] molMap;
557 // if( cardDeck != NULL ) delete[] cardDeck;
558 // if( locate != NULL ){
559 // for(i=0; i<bsInfo.nComponents; i++){
560 // delete locate[i];
561 // }
562 // delete[] locate;
563 // }
564 // if( atoms != NULL ){
565 // for(i=0; i<nAtoms; i++){
566 // delete atoms[i];
567 // }
568 // Atom::destroyArrays();
569 // delete[] atoms;
570 // }
571 // if( molSeq != NULL ) delete[] molSeq;
572 // if( simnfo != NULL ) delete simnfo;
573 // if( writer != NULL ) delete writer;
574
575 return 1;
576 }
577
578 void getRandomRot( double rot[3][3] ){
579
580 double theta, phi, psi;
581 double cosTheta;
582
583 // select random phi, psi, and cosTheta
584
585 phi = 2.0 * M_PI * drand48();
586 psi = 2.0 * M_PI * drand48();
587 cosTheta = (2.0 * drand48()) - 1.0; // sample cos -1 to 1
588
589 theta = acos( cosTheta );
590
591 rot[0][0] = (cos(phi) * cos(psi)) - (sin(phi) * cos(theta) * sin(psi));
592 rot[0][1] = (sin(phi) * cos(psi)) + (cos(phi) * cos(theta) * sin(psi));
593 rot[0][2] = sin(theta) * sin(psi);
594
595 rot[1][0] = -(cos(phi) * sin(psi)) - (sin(phi) * cos(theta) * cos(psi));
596 rot[1][1] = -(sin(phi) * sin(psi)) + (cos(phi) * cos(theta) * cos(psi));
597 rot[1][2] = sin(theta) * cos(psi);
598
599 rot[2][0] = sin(phi) * sin(theta);
600 rot[2][1] = -cos(phi) * sin(theta);
601 rot[2][2] = cos(theta);
602 }
603
604
605
606 void buildMap( double &x, double &y, double &z,
607 double boxX, double boxY, double boxZ ){
608
609 if(x < 0) x -= boxX * (double)( (int)( (x / boxX) - 0.5 ) );
610 else x -= boxX * (double)( (int)( (x / boxX ) + 0.5));
611
612 if(y < 0) y -= boxY * (double)( (int)( (y / boxY) - 0.5 ) );
613 else y -= boxY * (double)( (int)( (y / boxY ) + 0.5));
614
615 if(z < 0) z -= boxZ * (double)( (int)( (z / boxZ) - 0.5 ) );
616 else z -= boxZ * (double)( (int)( (z / boxZ ) + 0.5));
617 }