ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/utils/sysbuilder/bilayerSys.cpp
Revision: 817
Committed: Fri Oct 24 17:36:18 2003 UTC (21 years, 6 months ago) by gezelter
File size: 20442 byte(s)
Log Message:
work on bilayer builder

File Contents

# User Rev Content
1 mmeineke 707
2 chuckv 678 #include <iostream>
3 mmeineke 707 #include <vector>
4     #include <algorithm>
5 chuckv 678
6     #include <cstdlib>
7     #include <cstring>
8     #include <cmath>
9    
10 mmeineke 707
11 chuckv 678 #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 chuckv 700 #include "latticeBuilder.hpp"
20 chuckv 678
21 mmeineke 707 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 chuckv 678 void buildMap( double &x, double &y, double &z,
33 chuckv 700 double boxX, double boxY, double boxZ );
34 chuckv 678
35     int buildRandomBilayer( void );
36 gezelter 817 int buildLatticeBilayer( int isHexLattice,
37     double hexSpacing,
38     double aLat,
39     double bLat,
40     int targetNlipid,
41     double targetWaterLipidRatio,
42     double leafSpacing);
43 chuckv 678
44     void getRandomRot( double rot[3][3] );
45 gezelter 817 void getEulerRot( double theta, double phi, double psi, double rot[3][3] );
46     void getUnitRot( double unit[3], double rot[3][3] );
47 chuckv 678
48     int buildBilayer( int isRandom ){
49    
50     if( isRandom ){
51     return buildRandomBilayer();
52     }
53     else{
54 gezelter 817
55    
56    
57     return buildLatticeBilayer();
58 chuckv 678 }
59     }
60    
61    
62     int buildRandomBilayer( void ){
63    
64     typedef struct{
65     double rot[3][3];
66     double pos[3];
67     } coord;
68    
69    
70 chuckv 700
71 chuckv 678 const double waterRho = 0.0334; // number density per cubic angstrom
72     const double waterVol = 4.0 / waterRho; // volume occupied by 4 waters
73     const double waterCell = 4.929; // fcc unit cell length
74    
75 chuckv 700 Lattice myFCC( FCC_LATTICE_TYPE, waterCell );
76     double *posX, *posY, *posZ;
77     double pos[3], posA[3], posB[3];
78    
79 chuckv 678 const double water_padding = 6.0;
80     const double lipid_spaceing = 8.0;
81    
82    
83 chuckv 700 int i,j,k, l, m;
84 chuckv 678 int nAtoms, atomIndex, molIndex, molID;
85     int* molSeq;
86     int* molMap;
87     int* molStart;
88     int* cardDeck;
89     int deckSize;
90     int rSite, rCard;
91     double cell;
92     int nCells, nSites, siteIndex;
93    
94     coord testSite;
95    
96     Atom** atoms;
97     SimInfo* simnfo;
98 chuckv 700 SimState* theConfig;
99 chuckv 678 DumpWriter* writer;
100    
101     MoleculeStamp* lipidStamp;
102     MoleculeStamp* waterStamp;
103     MoLocator *lipidLocate;
104     MoLocator *waterLocate;
105     int foundLipid, foundWater;
106     int nLipids, lipidNatoms, nWaters, waterNatoms;
107     double testBox, maxLength;
108    
109     srand48( RAND_SEED );
110    
111    
112     // create the simInfo objects
113    
114     simnfo = new SimInfo[3];
115    
116    
117     // set the the lipidStamp
118    
119     foundLipid = 0;
120     foundWater = 0;
121     for(i=0; i<bsInfo.nComponents; i++){
122     if( !strcmp( bsInfo.compStamps[i]->getID(), bsInfo.lipidName ) ){
123 chuckv 700
124 chuckv 678 foundLipid = 1;
125     lipidStamp = bsInfo.compStamps[i];
126     nLipids = bsInfo.componentsNmol[i];
127     }
128     if( !strcmp( bsInfo.compStamps[i]->getID(), bsInfo.waterName ) ){
129 chuckv 700
130 chuckv 678 foundWater = 1;
131 chuckv 700
132 chuckv 678 waterStamp = bsInfo.compStamps[i];
133     nWaters = bsInfo.componentsNmol[i];
134     }
135     }
136     if( !foundLipid ){
137     sprintf(painCave.errMsg,
138     "Could not find lipid \"%s\" in the bass file.\n",
139     bsInfo.lipidName );
140     painCave.isFatal = 1;
141     simError();
142     }
143     if( !foundWater ){
144 chuckv 700 sprintf(painCave.errMsg,
145     "Could not find solvent \"%s\" in the bass file.\n",
146 chuckv 678 bsInfo.waterName );
147     painCave.isFatal = 1;
148     simError();
149     }
150    
151     //create the temp Molocator and atom Arrays
152    
153     lipidLocate = new MoLocator( lipidStamp );
154     lipidNatoms = lipidStamp->getNAtoms();
155     maxLength = lipidLocate->getMaxLength();
156    
157     waterLocate = new MoLocator( waterStamp );
158     waterNatoms = waterStamp->getNAtoms();
159    
160 chuckv 700 nAtoms = lipidNatoms;
161 chuckv 678
162 chuckv 700 simnfo[0].n_atoms = nAtoms;
163     simnfo[0].atoms=new Atom*[nAtoms];
164 chuckv 678
165 chuckv 700 theConfig = simnfo[0].getConfiguration();
166     theConfig->createArrays( simnfo[0].n_atoms );
167 chuckv 678
168 chuckv 700 atoms=simnfo[0].atoms;
169 chuckv 678
170    
171     // create the test box for initial water displacement
172    
173     testBox = maxLength + waterCell * 4.0; // pad with 4 cells
174     nCells = (int)( testBox / waterCell + 1.0 );
175     int testWaters = 4 * nCells * nCells * nCells;
176    
177     double* waterX = new double[testWaters];
178     double* waterY = new double[testWaters];
179     double* waterZ = new double[testWaters];
180    
181     double x0 = 0.0 - ( testBox * 0.5 );
182     double y0 = 0.0 - ( testBox * 0.5 );
183     double z0 = 0.0 - ( testBox * 0.5 );
184    
185    
186     // create an fcc lattice in the water box.
187    
188     int ndx = 0;
189     for( i=0; i < nCells; i++ ){
190     for( j=0; j < nCells; j++ ){
191     for( k=0; k < nCells; k++ ){
192 chuckv 700
193     myFCC.getLatticePoints(&posX, &posY, &posZ, i, j, k);
194     for(l=0; l<4; l++){
195     waterX[ndx]=posX[l];
196     waterY[ndx]=posY[l];
197     waterZ[ndx]=posZ[l];
198     ndx++;
199     }
200 chuckv 678 }
201     }
202     }
203    
204     // calculate the number of water's displaced by our lipid.
205    
206     testSite.rot[0][0] = 1.0;
207     testSite.rot[0][1] = 0.0;
208     testSite.rot[0][2] = 0.0;
209    
210     testSite.rot[1][0] = 0.0;
211     testSite.rot[1][1] = 1.0;
212     testSite.rot[1][2] = 0.0;
213    
214     testSite.rot[2][0] = 0.0;
215     testSite.rot[2][1] = 0.0;
216     testSite.rot[2][2] = 1.0;
217    
218     testSite.pos[0] = 0.0;
219     testSite.pos[1] = 0.0;
220     testSite.pos[2] = 0.0;
221    
222 chuckv 700 lipidLocate->placeMol( testSite.pos, testSite.rot, atoms, 0, theConfig );
223 chuckv 678
224     int *isActive = new int[testWaters];
225     for(i=0; i<testWaters; i++) isActive[i] = 1;
226    
227     int n_deleted = 0;
228     double dx, dy, dz;
229     double dx2, dy2, dz2, dSqr;
230     double rCutSqr = water_padding * water_padding;
231    
232     for(i=0; ( (i<testWaters) && isActive[i] ); i++){
233     for(j=0; ( (j<lipidNatoms) && isActive[i] ); j++){
234 chuckv 700
235     atoms[j]->getPos( pos );
236 chuckv 678
237 chuckv 700 dx = waterX[i] - pos[0];
238     dy = waterY[i] - pos[1];
239     dz = waterZ[i] - pos[2];
240 chuckv 678
241     buildMap( dx, dy, dz, testBox, testBox, testBox );
242    
243     dx2 = dx * dx;
244     dy2 = dy * dy;
245     dz2 = dz * dz;
246 chuckv 700
247 chuckv 678 dSqr = dx2 + dy2 + dz2;
248     if( dSqr < rCutSqr ){
249     isActive[i] = 0;
250     n_deleted++;
251     }
252     }
253     }
254    
255     int targetWaters = nWaters + n_deleted * nLipids;
256    
257     targetWaters = (int) ( targetWaters * 1.2 );
258    
259     // find the best box size for the sim
260    
261 mmeineke 707 int nCellsX, nCellsY, nCellsZ;
262    
263 tim 763 const double boxTargetX = 66.22752;
264     const double boxTargetY = 60.53088;
265 mmeineke 707
266     nCellsX = (int)ceil(boxTargetX / waterCell);
267     nCellsY = (int)ceil(boxTargetY / waterCell);
268    
269 chuckv 678 int testTot;
270     int done = 0;
271 mmeineke 707 nCellsZ = 0;
272 chuckv 678 while( !done ){
273 chuckv 700
274 mmeineke 707 nCellsZ++;
275     testTot = 4 * nCellsX * nCellsY * nCellsZ;
276 chuckv 700
277 chuckv 678 if( testTot >= targetWaters ) done = 1;
278     }
279    
280     // create the new water box to the new specifications
281    
282 mmeineke 707 int newWaters = nCellsX * nCellsY * nCellsZ * 4;
283 chuckv 678
284     delete[] waterX;
285     delete[] waterY;
286     delete[] waterZ;
287    
288     coord* waterSites = new coord[newWaters];
289    
290 mmeineke 707 double box_x = waterCell * nCellsX;
291     double box_y = waterCell * nCellsY;
292     double box_z = waterCell * nCellsZ;
293 chuckv 700
294 chuckv 678 // create an fcc lattice in the water box.
295    
296     ndx = 0;
297 mmeineke 707 for( i=0; i < nCellsX; i++ ){
298     for( j=0; j < nCellsY; j++ ){
299     for( k=0; k < nCellsZ; k++ ){
300 chuckv 700
301     myFCC.getLatticePoints(&posX, &posY, &posZ, i, j, k);
302     for(l=0; l<4; l++){
303     waterSites[ndx].pos[0] = posX[l];
304     waterSites[ndx].pos[1] = posY[l];
305     waterSites[ndx].pos[2] = posZ[l];
306     ndx++;
307     }
308 chuckv 678 }
309     }
310     }
311    
312     coord* lipidSites = new coord[nLipids];
313    
314     // start a 3D RSA for the for the lipid placements
315    
316    
317     int reject;
318     int testDX, acceptedDX;
319    
320 chuckv 700 nAtoms = nLipids * lipidNatoms;
321    
322     simnfo[1].n_atoms = nAtoms;
323     simnfo[1].atoms=new Atom*[nAtoms];
324    
325     theConfig = simnfo[1].getConfiguration();
326     theConfig->createArrays( simnfo[1].n_atoms );
327    
328     atoms=simnfo[1].atoms;
329    
330 chuckv 678 rCutSqr = lipid_spaceing * lipid_spaceing;
331    
332     for(i=0; i<nLipids; i++ ){
333     done = 0;
334     while( !done ){
335 chuckv 700
336 chuckv 678 lipidSites[i].pos[0] = drand48() * box_x;
337     lipidSites[i].pos[1] = drand48() * box_y;
338     lipidSites[i].pos[2] = drand48() * box_z;
339 chuckv 700
340 chuckv 678 getRandomRot( lipidSites[i].rot );
341 chuckv 700
342 chuckv 678 ndx = i * lipidNatoms;
343    
344     lipidLocate->placeMol( lipidSites[i].pos, lipidSites[i].rot, atoms,
345 chuckv 700 ndx, theConfig );
346    
347 chuckv 678 reject = 0;
348     for( j=0; !reject && j<i; j++){
349     for(k=0; !reject && k<lipidNatoms; k++){
350    
351     acceptedDX = j*lipidNatoms + k;
352     for(l=0; !reject && l<lipidNatoms; l++){
353 chuckv 700
354 chuckv 678 testDX = ndx + l;
355    
356 chuckv 700 atoms[testDX]->getPos( posA );
357     atoms[acceptedDX]->getPos( posB );
358 chuckv 678
359 chuckv 700 dx = posA[0] - posB[0];
360     dy = posA[1] - posB[1];
361     dz = posA[2] - posB[2];
362    
363 chuckv 678 buildMap( dx, dy, dz, box_x, box_y, box_z );
364 chuckv 700
365 chuckv 678 dx2 = dx * dx;
366     dy2 = dy * dy;
367     dz2 = dz * dz;
368 chuckv 700
369 chuckv 678 dSqr = dx2 + dy2 + dz2;
370     if( dSqr < rCutSqr ) reject = 1;
371     }
372     }
373     }
374    
375     if( reject ){
376    
377     for(j=0; j< lipidNatoms; j++) delete atoms[ndx+j];
378     }
379     else{
380     done = 1;
381 chuckv 700 std::cout << (i+1) << " has been accepted\n";
382 chuckv 678 }
383     }
384     }
385    
386 mmeineke 707
387     // zSort of the lipid positions
388    
389    
390     vector< pair<int,double> >zSortArray;
391     for(i=0;i<nLipids;i++)
392     zSortArray.push_back( make_pair(i, lipidSites[i].pos[2]) );
393    
394     sort(zSortArray.begin(),zSortArray.end(),SortCond());
395    
396 mmeineke 724 ofstream outFile( "./zipper.bass", ios::app);
397 mmeineke 707
398     for(i=0; i<nLipids; i++){
399     outFile << "zConstraint[" << i << "]{\n"
400     << " molIndex = " << zSortArray[i].first << ";\n"
401     << " zPos = ";
402    
403     if(i<32) outFile << "60.0;\n";
404     else outFile << "100.0;\n";
405    
406     outFile << " kRatio = 0.5;\n"
407     << "}\n";
408     }
409    
410     outFile.close();
411    
412    
413 chuckv 678 // cut out the waters that overlap with the lipids.
414    
415 chuckv 700
416 chuckv 678 delete[] isActive;
417     isActive = new int[newWaters];
418     for(i=0; i<newWaters; i++) isActive[i] = 1;
419     int n_active = newWaters;
420     rCutSqr = water_padding * water_padding;
421    
422     for(i=0; ( (i<newWaters) && isActive[i] ); i++){
423     for(j=0; ( (j<nAtoms) && isActive[i] ); j++){
424    
425 chuckv 700 atoms[j]->getPos( pos );
426 chuckv 678
427 chuckv 700 dx = waterSites[i].pos[0] - pos[0];
428     dy = waterSites[i].pos[1] - pos[1];
429     dz = waterSites[i].pos[2] - pos[2];
430    
431 chuckv 678 buildMap( dx, dy, dz, box_x, box_y, box_z );
432    
433     dx2 = dx * dx;
434     dy2 = dy * dy;
435     dz2 = dz * dz;
436 chuckv 700
437 chuckv 678 dSqr = dx2 + dy2 + dz2;
438     if( dSqr < rCutSqr ){
439     isActive[i] = 0;
440     n_active--;
441 chuckv 700
442    
443 chuckv 678 }
444     }
445     }
446    
447 chuckv 700
448    
449    
450 chuckv 678 if( n_active < nWaters ){
451 chuckv 700
452 chuckv 678 sprintf( painCave.errMsg,
453     "Too many waters were removed, edit code and try again.\n" );
454 chuckv 700
455 chuckv 678 painCave.isFatal = 1;
456     simError();
457     }
458    
459     int quickKill;
460     while( n_active > nWaters ){
461    
462     quickKill = (int)(drand48()*newWaters);
463    
464     if( isActive[quickKill] ){
465     isActive[quickKill] = 0;
466     n_active--;
467 chuckv 700
468 chuckv 678 }
469     }
470    
471     if( n_active != nWaters ){
472 chuckv 700
473 chuckv 678 sprintf( painCave.errMsg,
474     "QuickKill didn't work right. n_active = %d, and nWaters = %d\n",
475     n_active, nWaters );
476     painCave.isFatal = 1;
477     simError();
478     }
479    
480     // clean up our messes before building the final system.
481    
482 chuckv 700 simnfo[0].getConfiguration()->destroyArrays();
483     simnfo[1].getConfiguration()->destroyArrays();
484 chuckv 678
485     // create the real Atom arrays
486    
487     nAtoms = 0;
488     molIndex = 0;
489     molStart = new int[nLipids + nWaters];
490    
491     for(j=0; j<nLipids; j++){
492     molStart[molIndex] = nAtoms;
493     molIndex++;
494     nAtoms += lipidNatoms;
495     }
496    
497     for(j=0; j<nWaters; j++){
498     molStart[molIndex] = nAtoms;
499     molIndex++;
500     nAtoms += waterNatoms;
501     }
502    
503 chuckv 700 theConfig = simnfo[2].getConfiguration();
504     theConfig->createArrays( nAtoms );
505     simnfo[2].atoms = new Atom*[nAtoms];
506     atoms = simnfo[2].atoms;
507     simnfo[2].n_atoms = nAtoms;
508 chuckv 678
509     // initialize lipid positions
510    
511     molIndex = 0;
512     for(i=0; i<nLipids; i++ ){
513     lipidLocate->placeMol( lipidSites[i].pos, lipidSites[i].rot, atoms,
514 chuckv 700 molStart[molIndex], theConfig );
515 chuckv 678 molIndex++;
516     }
517    
518     // initialize the water positions
519    
520     for(i=0; i<newWaters; i++){
521 chuckv 700
522 chuckv 678 if( isActive[i] ){
523 chuckv 700
524 chuckv 678 getRandomRot( waterSites[i].rot );
525     waterLocate->placeMol( waterSites[i].pos, waterSites[i].rot, atoms,
526 chuckv 700 molStart[molIndex], theConfig );
527 chuckv 678 molIndex++;
528     }
529     }
530    
531     // set up the SimInfo object
532    
533 chuckv 700 double Hmat[3][3];
534    
535     Hmat[0][0] = box_x;
536     Hmat[0][1] = 0.0;
537     Hmat[0][2] = 0.0;
538    
539     Hmat[1][0] = 0.0;
540     Hmat[1][1] = box_y;
541     Hmat[1][2] = 0.0;
542    
543     Hmat[2][0] = 0.0;
544     Hmat[2][1] = 0.0;
545     Hmat[2][2] = box_z;
546    
547    
548 chuckv 678 bsInfo.boxX = box_x;
549     bsInfo.boxY = box_y;
550     bsInfo.boxZ = box_z;
551    
552 chuckv 700 simnfo[2].setBoxM( Hmat );
553 chuckv 678
554 chuckv 700 sprintf( simnfo[2].sampleName, "%s.dump", bsInfo.outPrefix );
555     sprintf( simnfo[2].finalName, "%s.init", bsInfo.outPrefix );
556 chuckv 678
557     // set up the writer and write out
558    
559 chuckv 700 writer = new DumpWriter( &simnfo[2] );
560 chuckv 678 writer->writeFinal( 0.0 );
561    
562     // clean up the memory
563    
564 chuckv 700 // if( molMap != NULL ) delete[] molMap;
565     // if( cardDeck != NULL ) delete[] cardDeck;
566     // if( locate != NULL ){
567     // for(i=0; i<bsInfo.nComponents; i++){
568     // delete locate[i];
569     // }
570     // delete[] locate;
571     // }
572     // if( atoms != NULL ){
573     // for(i=0; i<nAtoms; i++){
574     // delete atoms[i];
575     // }
576     // Atom::destroyArrays();
577     // delete[] atoms;
578     // }
579     // if( molSeq != NULL ) delete[] molSeq;
580     // if( simnfo != NULL ) delete simnfo;
581     // if( writer != NULL ) delete writer;
582 chuckv 678
583     return 1;
584     }
585    
586 gezelter 817 int buildLatticeBilayer(int isHexLattice,
587     double hexSpacing,
588     double aLat,
589     double bLat,
590     int targetNlipid,
591     double targetWaterLipidRatio,
592     double leafSpacing){
593    
594     typedef struct{
595     double rot[3][3];
596     double pos[3];
597     } coord;
598    
599     const double waterRho = 0.0334; // number density per cubic angstrom
600     const double waterVol = 4.0 / waterRho; // volume occupied by 4 waters
601    
602     double waterCell[3];
603    
604     double *posX, *posY, *posZ;
605     double pos[3], posA[3], posB[3];
606    
607     const double waterFudge = 5.0;
608    
609     int i,j,k,l;
610     int nAtoms, atomIndex, molIndex, molID;
611     int* molSeq;
612     int* molMap;
613     int* molStart;
614     int testTot, done;
615     int nCells, nCellsX, nCellsY, nCellsZ;
616     int nx, ny;
617     double boxX, boxY, boxZ;
618     double unitVector[3];
619     int which;
620     int targetWaters;
621    
622    
623    
624     coord testSite;
625    
626     Atom** atoms;
627     SimInfo* simnfo;
628     SimState* theConfig;
629     DumpWriter* writer;
630    
631     MoleculeStamp* lipidStamp;
632     MoleculeStamp* waterStamp;
633     MoLocator *lipidLocate;
634     MoLocator *waterLocate;
635     int foundLipid, foundWater;
636     int nLipids, lipidNatoms, nWaters, waterNatoms;
637    
638     srand48( RAND_SEED );
639    
640     // create the simInfo objects
641    
642     simnfo = new SimInfo;
643    
644     // set the the lipidStamp
645    
646     foundLipid = 0;
647     foundWater = 0;
648     for(i=0; i<bsInfo.nComponents; i++){
649     if( !strcmp( bsInfo.compStamps[i]->getID(), bsInfo.lipidName ) ){
650    
651     foundLipid = 1;
652     lipidStamp = bsInfo.compStamps[i];
653     nLipids = bsInfo.componentsNmol[i];
654     lipidNatoms = lipidStamp->getNAtoms();
655     }
656     if( !strcmp( bsInfo.compStamps[i]->getID(), bsInfo.waterName ) ){
657    
658     foundWater = 1;
659    
660     waterStamp = bsInfo.compStamps[i];
661     nWaters = bsInfo.componentsNmol[i];
662     waterNatoms = waterStamp->getNAtoms();
663     }
664     }
665     if( !foundLipid ){
666     sprintf(painCave.errMsg,
667     "Could not find lipid \"%s\" in the bass file.\n",
668     bsInfo.lipidName );
669     painCave.isFatal = 1;
670     simError();
671     }
672     if( !foundWater ){
673     sprintf(painCave.errMsg,
674     "Could not find solvent \"%s\" in the bass file.\n",
675     bsInfo.waterName );
676     painCave.isFatal = 1;
677     simError();
678     }
679    
680     //create the Molocator arrays
681    
682     lipidLocate = new MoLocator( lipidStamp );
683     waterLocate = new MoLocator( waterStamp );
684    
685    
686     // set up the bilayer leaves
687    
688     if (isHexLattice) {
689     aLat = sqrt(3.0)*hexSpacing;
690     bLat = hexSpacing;
691     }
692    
693     nCells = (int) sqrt( (double)targetNlipid * bLat / (4.0 * aLat) );
694    
695     nx = nCells;
696     ny = (int) ((double)nCells * aLat / bLat);
697    
698     boxX = nx * aLat;
699     boxY = ny * bLat;
700    
701     nLipids = 4 * nx * ny;
702     coord* lipidSites = new coord[nLipids];
703    
704     unitVector[0] = 0.0;
705     unitVector[1] = 0.0;
706    
707     which = 0;
708    
709     for (i = 0; i < nx; i++) {
710     for (j = 0; j < ny; j++ ) {
711     for (k = 0; k < 2; k++) {
712    
713     lipidSites[which].pos[0] = (double)i * aLat;
714     lipidSites[which].pos[1] = (double)j * bLat;
715     lipidSites[which].pos[2] = ((double)k - 0.5) * (leafSpacing / 2.0);
716    
717     unitVector[2] = 2.0 * (double)k - 1.0;
718    
719     getUnitRot( unitVector, lipidSites[which].rot );
720    
721     which++;
722    
723     lipidSites[which].pos[0] = aLat * ((double)i + 0.5);
724     lipidSites[which].pos[1] = bLat * ((double)j + 0.5);
725     lipidSites[which].pos[2] = ((double)k - 0.5) * (leafSpacing / 2.0);
726    
727     unitVector[2] = 2.0 * (double)k - 1.0;
728    
729     getUnitRot( unitVector, lipidSites[which].rot );
730    
731     which++;
732     }
733     }
734     }
735    
736     targetWaters = targetWaterLipidRatio * nLipids;
737    
738     // guess the size of the water box
739    
740    
741    
742     nCellsX = (int)ceil(boxX / pow(waterVol, ( 1.0 / 3.0 )) );
743     nCellsY = (int)ceil(boxY / pow(waterVol, ( 1.0 / 3.0 )) );
744    
745     done = 0;
746     nCellsZ = 0;
747     while( !done ){
748    
749     nCellsZ++;
750     testTot = 4 * nCellsX * nCellsY * nCellsZ;
751    
752     if( testTot >= targetWaters ) done = 1;
753     }
754    
755     nWaters = nCellsX * nCellsY * nCellsZ * 4;
756    
757     coord* waterSites = new coord[nWaters];
758    
759     waterCell[0] = boxX / nCellsX;
760     waterCell[1] = boxY / nCellsY;
761     waterCell[2] = 4.0 / (waterRho * waterCell[0] * waterCell[1]);
762    
763     Lattice *myORTHO;
764     myORTHO = new Lattice( ORTHORHOMBIC_LATTICE_TYPE, waterCell);
765     myORTHO->setStartZ( leafSpacing / 2.0 + waterFudge);
766    
767     boxZ = waterCell[2] * nCellsZ;
768    
769     // create an fcc lattice in the water box.
770    
771     which = 0;
772     for( i=0; i < nCellsX; i++ ){
773     for( j=0; j < nCellsY; j++ ){
774     for( k=0; k < nCellsZ; k++ ){
775    
776     myORTHO->getLatticePoints(&posX, &posY, &posZ, i, j, k);
777     for(l=0; l<4; l++){
778     waterSites[which].pos[0] = posX[l];
779     waterSites[which].pos[1] = posY[l];
780     waterSites[which].pos[2] = posZ[l];
781     which++;
782     }
783     }
784     }
785     }
786    
787     // create the real Atom arrays
788    
789     nAtoms = 0;
790     molIndex = 0;
791     molStart = new int[nLipids + nWaters];
792    
793     for(j=0; j<nLipids; j++){
794     molStart[molIndex] = nAtoms;
795     molIndex++;
796     nAtoms += lipidNatoms;
797     }
798    
799     for(j=0; j<nWaters; j++){
800     molStart[molIndex] = nAtoms;
801     molIndex++;
802     nAtoms += waterNatoms;
803     }
804    
805     theConfig = simnfo->getConfiguration();
806     theConfig->createArrays( nAtoms );
807     simnfo->atoms = new Atom*[nAtoms];
808     atoms = simnfo->atoms;
809    
810     // initialize lipid positions
811    
812     molIndex = 0;
813     for(i=0; i<nLipids; i++ ){
814     lipidLocate->placeMol( lipidSites[i].pos, lipidSites[i].rot, atoms,
815     molStart[molIndex], theConfig );
816     molIndex++;
817     }
818    
819     // initialize the water positions
820    
821     for(i=0; i<nWaters; i++){
822    
823     getRandomRot( waterSites[i].rot );
824     waterLocate->placeMol( waterSites[i].pos, waterSites[i].rot, atoms,
825     molStart[molIndex], theConfig );
826     molIndex++;
827     }
828    
829     // set up the SimInfo object
830    
831     double Hmat[3][3];
832    
833     Hmat[0][0] = boxX;
834     Hmat[0][1] = 0.0;
835     Hmat[0][2] = 0.0;
836    
837     Hmat[1][0] = 0.0;
838     Hmat[1][1] = boxY;
839     Hmat[1][2] = 0.0;
840    
841     Hmat[2][0] = 0.0;
842     Hmat[2][1] = 0.0;
843     Hmat[2][2] = boxZ;
844    
845    
846     bsInfo.boxX = boxX;
847     bsInfo.boxY = boxY;
848     bsInfo.boxZ = boxZ;
849    
850     simnfo->setBoxM( Hmat );
851    
852     sprintf( simnfo->sampleName, "%s.dump", bsInfo.outPrefix );
853     sprintf( simnfo->finalName, "%s.init", bsInfo.outPrefix );
854    
855     // set up the writer and write out
856    
857     writer = new DumpWriter( simnfo );
858     writer->writeFinal( 0.0 );
859    
860     return 1;
861     }
862    
863    
864 chuckv 678 void getRandomRot( double rot[3][3] ){
865    
866     double theta, phi, psi;
867     double cosTheta;
868    
869     // select random phi, psi, and cosTheta
870    
871     phi = 2.0 * M_PI * drand48();
872     psi = 2.0 * M_PI * drand48();
873     cosTheta = (2.0 * drand48()) - 1.0; // sample cos -1 to 1
874    
875     theta = acos( cosTheta );
876    
877 gezelter 817 getEulerRot( theta, phi, psi, rot );
878     }
879    
880    
881     void getEulerRot( double theta, double phi, double psi, double rot[3][3] ){
882    
883 chuckv 678 rot[0][0] = (cos(phi) * cos(psi)) - (sin(phi) * cos(theta) * sin(psi));
884     rot[0][1] = (sin(phi) * cos(psi)) + (cos(phi) * cos(theta) * sin(psi));
885     rot[0][2] = sin(theta) * sin(psi);
886    
887     rot[1][0] = -(cos(phi) * sin(psi)) - (sin(phi) * cos(theta) * cos(psi));
888     rot[1][1] = -(sin(phi) * sin(psi)) + (cos(phi) * cos(theta) * cos(psi));
889     rot[1][2] = sin(theta) * cos(psi);
890    
891     rot[2][0] = sin(phi) * sin(theta);
892     rot[2][1] = -cos(phi) * sin(theta);
893     rot[2][2] = cos(theta);
894     }
895 gezelter 817
896    
897     void getUnitRot( double u[3], double rot[3][3] ){
898    
899     double theta, phi, psi;
900    
901     theta = acos(u[2]);
902     phi = atan(u[1] / u[0]);
903     psi = 0.0;
904    
905     getEulerRot( theta, phi, psi, rot );
906     }
907 chuckv 678
908    
909    
910     void buildMap( double &x, double &y, double &z,
911 chuckv 700 double boxX, double boxY, double boxZ ){
912 chuckv 678
913     if(x < 0) x -= boxX * (double)( (int)( (x / boxX) - 0.5 ) );
914     else x -= boxX * (double)( (int)( (x / boxX ) + 0.5));
915    
916     if(y < 0) y -= boxY * (double)( (int)( (y / boxY) - 0.5 ) );
917     else y -= boxY * (double)( (int)( (y / boxY ) + 0.5));
918    
919     if(z < 0) z -= boxZ * (double)( (int)( (z / boxZ) - 0.5 ) );
920     else z -= boxZ * (double)( (int)( (z / boxZ ) + 0.5));
921     }