ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/utils/sysbuilder/bilayerSys.cpp
Revision: 678
Committed: Mon Aug 11 22:12:31 2003 UTC (21 years, 8 months ago) by chuckv
File size: 17305 byte(s)
Log Message:
Arranged sysbuilder into a subdirectory. Fixed some of sysbuilder to work with new
atom allocation in libmdtools.

File Contents

# User Rev Content
1 chuckv 678 #include <iostream>
2    
3     #include <cstdlib>
4     #include <cstring>
5     #include <cmath>
6    
7     #include "simError.h"
8     #include "SimInfo.hpp"
9     #include "ReadWrite.hpp"
10    
11     #include "MoLocator.hpp"
12     #include "sysBuild.hpp"
13     #include "bilayerSys.hpp"
14    
15    
16    
17     void buildMap( double &x, double &y, double &z,
18     double boxX, double boxY, double boxZ );
19    
20     int buildRandomBilayer( void );
21    
22     void getRandomRot( double rot[3][3] );
23    
24     int buildBilayer( int isRandom ){
25    
26     if( isRandom ){
27     return buildRandomBilayer();
28     }
29     else{
30     sprintf( painCave.errMsg,
31     "Cannot currently create a non-random bilayer.\n" );
32     painCave.isFatal = 1;
33     simError();
34     return 0;
35     }
36     }
37    
38    
39     int buildRandomBilayer( void ){
40    
41     typedef struct{
42     double rot[3][3];
43     double pos[3];
44     } coord;
45    
46    
47     const double waterRho = 0.0334; // number density per cubic angstrom
48     const double waterVol = 4.0 / waterRho; // volume occupied by 4 waters
49     const double waterCell = 4.929; // fcc unit cell length
50    
51     const double water_padding = 6.0;
52     const double lipid_spaceing = 8.0;
53    
54    
55     int i,j,k, l;
56     int nAtoms, atomIndex, molIndex, molID;
57     int* molSeq;
58     int* molMap;
59     int* molStart;
60     int* cardDeck;
61     int deckSize;
62     int rSite, rCard;
63     double cell;
64     int nCells, nSites, siteIndex;
65    
66     coord testSite;
67    
68     Atom** atoms;
69     SimInfo* simnfo;
70     DumpWriter* writer;
71    
72     MoleculeStamp* lipidStamp;
73     MoleculeStamp* waterStamp;
74     MoLocator *lipidLocate;
75     MoLocator *waterLocate;
76     int foundLipid, foundWater;
77     int nLipids, lipidNatoms, nWaters, waterNatoms;
78     double testBox, maxLength;
79    
80     srand48( RAND_SEED );
81    
82    
83     // create the simInfo objects
84    
85     simnfo = new SimInfo[3];
86    
87    
88     // set the the lipidStamp
89    
90     foundLipid = 0;
91     foundWater = 0;
92     for(i=0; i<bsInfo.nComponents; i++){
93     if( !strcmp( bsInfo.compStamps[i]->getID(), bsInfo.lipidName ) ){
94    
95     foundLipid = 1;
96     lipidStamp = bsInfo.compStamps[i];
97     nLipids = bsInfo.componentsNmol[i];
98     }
99     if( !strcmp( bsInfo.compStamps[i]->getID(), bsInfo.waterName ) ){
100    
101     foundWater = 1;
102    
103     waterStamp = bsInfo.compStamps[i];
104     nWaters = bsInfo.componentsNmol[i];
105     }
106     }
107     if( !foundLipid ){
108     sprintf(painCave.errMsg,
109     "Could not find lipid \"%s\" in the bass file.\n",
110     bsInfo.lipidName );
111     painCave.isFatal = 1;
112     simError();
113     }
114     if( !foundWater ){
115     sprintf(painCave.errMsg,
116     "Could not find solvent \"%s\" in the bass file.\n",
117     bsInfo.waterName );
118     painCave.isFatal = 1;
119     simError();
120     }
121    
122     //create the temp Molocator and atom Arrays
123    
124     lipidLocate = new MoLocator( lipidStamp );
125     lipidNatoms = lipidStamp->getNAtoms();
126     maxLength = lipidLocate->getMaxLength();
127    
128     waterLocate = new MoLocator( waterStamp );
129     waterNatoms = waterStamp->getNAtoms();
130    
131     nAtoms = nLipids * lipidNatoms;
132    
133     simnfo[0].n_atoms = nAtoms;
134     simnfo[0].atoms=new Atom*[nAtoms];
135    
136     (simnfo[0]->getConfiguration())->createArrays( simnfo[0].n_atoms );
137     for(i=0; i<simnfo[0].n_atoms; i++) simnfo[0].atoms[i]->setCoords();
138    
139     atoms=simnfo[0].atoms;
140    
141    
142     // create the test box for initial water displacement
143    
144     testBox = maxLength + waterCell * 4.0; // pad with 4 cells
145     nCells = (int)( testBox / waterCell + 1.0 );
146     int testWaters = 4 * nCells * nCells * nCells;
147    
148     double* waterX = new double[testWaters];
149     double* waterY = new double[testWaters];
150     double* waterZ = new double[testWaters];
151    
152     double x0 = 0.0 - ( testBox * 0.5 );
153     double y0 = 0.0 - ( testBox * 0.5 );
154     double z0 = 0.0 - ( testBox * 0.5 );
155    
156    
157     // create an fcc lattice in the water box.
158    
159     int ndx = 0;
160     for( i=0; i < nCells; i++ ){
161     for( j=0; j < nCells; j++ ){
162     for( k=0; k < nCells; k++ ){
163    
164     waterX[ndx] = i * waterCell + x0;
165     waterY[ndx] = j * waterCell + y0;
166     waterZ[ndx] = k * waterCell + z0;
167     ndx++;
168    
169     waterX[ndx] = i * waterCell + 0.5 * waterCell + x0;
170     waterY[ndx] = j * waterCell + 0.5 * waterCell + y0;
171     waterZ[ndx] = k * waterCell + z0;
172     ndx++;
173    
174     waterX[ndx] = i * waterCell + x0;
175     waterY[ndx] = j * waterCell + 0.5 * waterCell + y0;
176     waterZ[ndx] = k * waterCell + 0.5 * waterCell + z0;
177     ndx++;
178    
179     waterX[ndx] = i * waterCell + 0.5 * waterCell + x0;
180     waterY[ndx] = j * waterCell + y0;
181     waterZ[ndx] = k * waterCell + 0.5 * waterCell + z0;
182     ndx++;
183     }
184     }
185     }
186    
187     // calculate the number of water's displaced by our lipid.
188    
189     testSite.rot[0][0] = 1.0;
190     testSite.rot[0][1] = 0.0;
191     testSite.rot[0][2] = 0.0;
192    
193     testSite.rot[1][0] = 0.0;
194     testSite.rot[1][1] = 1.0;
195     testSite.rot[1][2] = 0.0;
196    
197     testSite.rot[2][0] = 0.0;
198     testSite.rot[2][1] = 0.0;
199     testSite.rot[2][2] = 1.0;
200    
201     testSite.pos[0] = 0.0;
202     testSite.pos[1] = 0.0;
203     testSite.pos[2] = 0.0;
204    
205     lipidLocate->placeMol( testSite.pos, testSite.rot, atoms, 0 );
206    
207     int *isActive = new int[testWaters];
208     for(i=0; i<testWaters; i++) isActive[i] = 1;
209    
210     int n_deleted = 0;
211     double dx, dy, dz;
212     double dx2, dy2, dz2, dSqr;
213     double rCutSqr = water_padding * water_padding;
214    
215     for(i=0; ( (i<testWaters) && isActive[i] ); i++){
216     for(j=0; ( (j<lipidNatoms) && isActive[i] ); j++){
217    
218     dx = waterX[i] - atoms[j]->getX();
219     dy = waterY[i] - atoms[j]->getY();
220     dz = waterZ[i] - atoms[j]->getZ();
221    
222     buildMap( dx, dy, dz, testBox, testBox, testBox );
223    
224     dx2 = dx * dx;
225     dy2 = dy * dy;
226     dz2 = dz * dz;
227    
228     dSqr = dx2 + dy2 + dz2;
229     if( dSqr < rCutSqr ){
230     isActive[i] = 0;
231     n_deleted++;
232     }
233     }
234     }
235    
236     int targetWaters = nWaters + n_deleted * nLipids;
237    
238     targetWaters = (int) ( targetWaters * 1.2 );
239    
240     // find the best box size for the sim
241    
242     int testTot;
243     int done = 0;
244     ndx = 0;
245     while( !done ){
246    
247     ndx++;
248     testTot = 4 * ndx * ndx * ndx;
249    
250     if( testTot >= targetWaters ) done = 1;
251     }
252    
253     nCells = ndx;
254    
255    
256     // create the new water box to the new specifications
257    
258     int newWaters = nCells * nCells * nCells * 4;
259    
260     delete[] waterX;
261     delete[] waterY;
262     delete[] waterZ;
263    
264     coord* waterSites = new coord[newWaters];
265    
266     double box_x = waterCell * nCells;
267     double box_y = waterCell * nCells;
268     double box_z = waterCell * nCells;
269    
270     // create an fcc lattice in the water box.
271    
272     ndx = 0;
273     for( i=0; i < nCells; i++ ){
274     for( j=0; j < nCells; j++ ){
275     for( k=0; k < nCells; k++ ){
276    
277     waterSites[ndx].pos[0] = i * waterCell;
278     waterSites[ndx].pos[1] = j * waterCell;
279     waterSites[ndx].pos[2] = k * waterCell;
280     ndx++;
281    
282     waterSites[ndx].pos[0] = i * waterCell + 0.5 * waterCell;
283     waterSites[ndx].pos[1] = j * waterCell + 0.5 * waterCell;
284     waterSites[ndx].pos[2] = k * waterCell;
285     ndx++;
286    
287     waterSites[ndx].pos[0] = i * waterCell;
288     waterSites[ndx].pos[1] = j * waterCell + 0.5 * waterCell;
289     waterSites[ndx].pos[2] = k * waterCell + 0.5 * waterCell;
290     ndx++;
291    
292     waterSites[ndx].pos[0] = i * waterCell + 0.5 * waterCell;
293     waterSites[ndx].pos[1] = j * waterCell;
294     waterSites[ndx].pos[2] = k * waterCell + 0.5 * waterCell;
295     ndx++;
296     }
297     }
298     }
299    
300     coord* lipidSites = new coord[nLipids];
301    
302     // start a 3D RSA for the for the lipid placements
303    
304    
305     int reject;
306     int testDX, acceptedDX;
307    
308     rCutSqr = lipid_spaceing * lipid_spaceing;
309    
310     for(i=0; i<nLipids; i++ ){
311     done = 0;
312     while( !done ){
313    
314     lipidSites[i].pos[0] = drand48() * box_x;
315     lipidSites[i].pos[1] = drand48() * box_y;
316     lipidSites[i].pos[2] = drand48() * box_z;
317    
318     getRandomRot( lipidSites[i].rot );
319    
320     ndx = i * lipidNatoms;
321    
322     lipidLocate->placeMol( lipidSites[i].pos, lipidSites[i].rot, atoms,
323     ndx );
324    
325     reject = 0;
326     for( j=0; !reject && j<i; j++){
327     for(k=0; !reject && k<lipidNatoms; k++){
328    
329     acceptedDX = j*lipidNatoms + k;
330     for(l=0; !reject && l<lipidNatoms; l++){
331    
332     testDX = ndx + l;
333    
334     dx = atoms[testDX]->getX() - atoms[acceptedDX]->getX();
335     dy = atoms[testDX]->getY() - atoms[acceptedDX]->getY();
336     dz = atoms[testDX]->getZ() - atoms[acceptedDX]->getZ();
337    
338     buildMap( dx, dy, dz, box_x, box_y, box_z );
339    
340     dx2 = dx * dx;
341     dy2 = dy * dy;
342     dz2 = dz * dz;
343    
344     dSqr = dx2 + dy2 + dz2;
345     if( dSqr < rCutSqr ) reject = 1;
346     }
347     }
348     }
349    
350     if( reject ){
351    
352     for(j=0; j< lipidNatoms; j++) delete atoms[ndx+j];
353     }
354     else{
355     done = 1;
356     std::cout << i << " has been accepted\n";
357     }
358     }
359     }
360    
361     // cut out the waters that overlap with the lipids.
362    
363     delete[] isActive;
364     isActive = new int[newWaters];
365     for(i=0; i<newWaters; i++) isActive[i] = 1;
366     int n_active = newWaters;
367     rCutSqr = water_padding * water_padding;
368    
369     for(i=0; ( (i<newWaters) && isActive[i] ); i++){
370     for(j=0; ( (j<nAtoms) && isActive[i] ); j++){
371    
372     dx = waterSites[i].pos[0] - atoms[j]->getX();
373     dy = waterSites[i].pos[1] - atoms[j]->getY();
374     dz = waterSites[i].pos[2] - atoms[j]->getZ();
375    
376     buildMap( dx, dy, dz, box_x, box_y, box_z );
377    
378     dx2 = dx * dx;
379     dy2 = dy * dy;
380     dz2 = dz * dz;
381    
382     dSqr = dx2 + dy2 + dz2;
383     if( dSqr < rCutSqr ){
384     isActive[i] = 0;
385     n_active--;
386     }
387     }
388     }
389    
390     if( n_active < nWaters ){
391    
392     sprintf( painCave.errMsg,
393     "Too many waters were removed, edit code and try again.\n" );
394    
395     painCave.isFatal = 1;
396     simError();
397     }
398    
399     int quickKill;
400     while( n_active > nWaters ){
401    
402     quickKill = (int)(drand48()*newWaters);
403    
404     if( isActive[quickKill] ){
405     isActive[quickKill] = 0;
406     n_active--;
407     }
408     }
409    
410     if( n_active != nWaters ){
411    
412     sprintf( painCave.errMsg,
413     "QuickKill didn't work right. n_active = %d, and nWaters = %d\n",
414     n_active, nWaters );
415     painCave.isFatal = 1;
416     simError();
417     }
418    
419     // clean up our messes before building the final system.
420    
421     for(i=0; i<nAtoms; i++){
422    
423     delete atoms[i];
424     }
425     Atom::destroyArrays();
426    
427    
428     // create the real Atom arrays
429    
430     nAtoms = 0;
431     molIndex = 0;
432     molStart = new int[nLipids + nWaters];
433    
434     for(j=0; j<nLipids; j++){
435     molStart[molIndex] = nAtoms;
436     molIndex++;
437     nAtoms += lipidNatoms;
438     }
439    
440     for(j=0; j<nWaters; j++){
441     molStart[molIndex] = nAtoms;
442     molIndex++;
443     nAtoms += waterNatoms;
444     }
445    
446    
447     Atom::createArrays( nAtoms );
448     atoms = new Atom*[nAtoms];
449    
450    
451     // initialize lipid positions
452    
453     molIndex = 0;
454     for(i=0; i<nLipids; i++ ){
455     lipidLocate->placeMol( lipidSites[i].pos, lipidSites[i].rot, atoms,
456     molStart[molIndex] );
457     molIndex++;
458     }
459    
460     // initialize the water positions
461    
462     for(i=0; i<newWaters; i++){
463    
464     if( isActive[i] ){
465    
466     getRandomRot( waterSites[i].rot );
467     waterLocate->placeMol( waterSites[i].pos, waterSites[i].rot, atoms,
468     molStart[molIndex] );
469     molIndex++;
470     }
471     }
472    
473     // set up the SimInfo object
474    
475     bsInfo.boxX = box_x;
476     bsInfo.boxY = box_y;
477     bsInfo.boxZ = box_z;
478    
479     double boxVector[3];
480    
481     boxVector[0] = bsInfo.boxX;
482     boxVector[1] = bsInfo.boxY;
483     boxVector[2] = bsInfo.boxZ;
484     simnfo->setBox( boxVector );
485    
486     sprintf( simnfo->sampleName, "%s.dump", bsInfo.outPrefix );
487     sprintf( simnfo->finalName, "%s.init", bsInfo.outPrefix );
488    
489     simnfo->atoms = atoms;
490    
491     // set up the writer and write out
492    
493     writer = new DumpWriter( simnfo );
494     writer->writeFinal( 0.0 );
495    
496     // clean up the memory
497    
498     // if( molMap != NULL ) delete[] molMap;
499     // if( cardDeck != NULL ) delete[] cardDeck;
500     // if( locate != NULL ){
501     // for(i=0; i<bsInfo.nComponents; i++){
502     // delete locate[i];
503     // }
504     // delete[] locate;
505     // }
506     // if( atoms != NULL ){
507     // for(i=0; i<nAtoms; i++){
508     // delete atoms[i];
509     // }
510     // Atom::destroyArrays();
511     // delete[] atoms;
512     // }
513     // if( molSeq != NULL ) delete[] molSeq;
514     // if( simnfo != NULL ) delete simnfo;
515     // if( writer != NULL ) delete writer;
516    
517     return 1;
518     }
519    
520    
521    
522     int Old_buildRandomBilayer( void ){
523    
524     int i,j,k;
525     int nAtoms, atomIndex, molIndex, molID;
526     int* molSeq;
527     int* molMap;
528     int* molStart;
529     int* cardDeck;
530     int deckSize;
531     int rSite, rCard;
532     double cell;
533     int nCells, nSites, siteIndex;
534     double rot[3][3];
535     double pos[3];
536    
537     Atom** atoms;
538     SimInfo* simnfo;
539     DumpWriter* writer;
540     MoLocator** locate;
541    
542     // initialize functions and variables
543    
544     srand48( RAND_SEED );
545     molSeq = NULL;
546     molStart = NULL;
547     molMap = NULL;
548     cardDeck = NULL;
549     atoms = NULL;
550     locate = NULL;
551     simnfo = NULL;
552     writer = NULL;
553    
554     // calculate the number of cells in the fcc box
555    
556     nCells = 0;
557     nSites = 0;
558     while( nSites < bsInfo.totNmol ){
559     nCells++;
560     nSites = 4.0 * pow( (double)nCells, 3.0 );
561     }
562    
563    
564     // create the molMap and cardDeck arrays
565    
566     molMap = new int[nSites];
567     cardDeck = new int[nSites];
568    
569     for(i=0; i<nSites; i++){
570     molMap[i] = -1;
571     cardDeck[i] = i;
572     }
573    
574     // randomly place the molecules on the sites
575    
576     deckSize = nSites;
577     for(i=0; i<bsInfo.totNmol; i++){
578     rCard = (int)( deckSize * drand48() );
579     rSite = cardDeck[rCard];
580     molMap[rSite] = i;
581    
582     // book keep the card deck;
583    
584     deckSize--;
585     cardDeck[rCard] = cardDeck[deckSize];
586     }
587    
588    
589     // create the MoLocator and Atom arrays
590    
591     nAtoms = 0;
592     molIndex = 0;
593     locate = new MoLocator*[bsInfo.nComponents];
594     molSeq = new int[bsInfo.totNmol];
595     molStart = new int[bsInfo.totNmol];
596     for(i=0; i<bsInfo.nComponents; i++){
597     locate[i] = new MoLocator( bsInfo.compStamps[i] );
598     for(j=0; j<bsInfo.componentsNmol[i]; j++){
599     molSeq[molIndex] = i;
600     molStart[molIndex] = nAtoms;
601     molIndex++;
602     nAtoms += bsInfo.compStamps[i]->getNAtoms();
603     }
604     }
605    
606     Atom::createArrays( nAtoms );
607     atoms = new Atom*[nAtoms];
608    
609    
610     // place the molecules at each FCC site
611    
612     cell = 5.0;
613     for(i=0; i<bsInfo.nComponents; i++){
614     if(cell < locate[i]->getMaxLength() ) cell = locate[i]->getMaxLength();
615     }
616     cell *= 1.2; // add a little buffer
617    
618     cell *= M_SQRT2;
619    
620     siteIndex = 0;
621     for(i=0; i<nCells; i++){
622     for(j=0; j<nCells; j++){
623     for(k=0; k<nCells; k++){
624    
625     if( molMap[siteIndex] >= 0 ){
626     pos[0] = i * cell;
627     pos[1] = j * cell;
628     pos[2] = k * cell;
629    
630     getRandomRot( rot );
631     molID = molSeq[molMap[siteIndex]];
632     atomIndex = molStart[ molMap[siteIndex] ];
633     locate[molID]->placeMol( pos, rot, atoms, atomIndex );
634     }
635     siteIndex++;
636    
637     if( molMap[siteIndex] >= 0 ){
638     pos[0] = i * cell + (0.5 * cell);
639     pos[1] = j * cell;
640     pos[2] = k * cell + (0.5 * cell);
641    
642     getRandomRot( rot );
643     molID = molSeq[molMap[siteIndex]];
644     atomIndex = molStart[ molMap[siteIndex] ];
645     locate[molID]->placeMol( pos, rot, atoms, atomIndex );
646     }
647     siteIndex++;
648    
649     if( molMap[siteIndex] >= 0 ){
650     pos[0] = i * cell + (0.5 * cell);
651     pos[1] = j * cell + (0.5 * cell);
652     pos[2] = k * cell;
653    
654     getRandomRot( rot );
655     molID = molSeq[molMap[siteIndex]];
656     atomIndex = molStart[ molMap[siteIndex] ];
657     locate[molID]->placeMol( pos, rot, atoms, atomIndex );
658     }
659     siteIndex++;
660    
661     if( molMap[siteIndex] >= 0 ){
662     pos[0] = i * cell;
663     pos[1] = j * cell + (0.5 * cell);
664     pos[2] = k * cell + (0.5 * cell);
665    
666     getRandomRot( rot );
667     molID = molSeq[molMap[siteIndex]];
668     atomIndex = molStart[ molMap[siteIndex] ];
669     locate[molID]->placeMol( pos, rot, atoms, atomIndex );
670     }
671     siteIndex++;
672     }
673     }
674     }
675    
676     // set up the SimInfo object
677    
678     bsInfo.boxX = nCells * cell;
679     bsInfo.boxY = nCells * cell;
680     bsInfo.boxZ = nCells * cell;
681    
682     double boxVector[3];
683     simnfo = new SimInfo();
684     simnfo->n_atoms = nAtoms;
685     boxVector[0] = bsInfo.boxX;
686     boxVector[1] = bsInfo.boxY;
687     boxVector[2] = bsInfo.boxZ;
688     simnfo->setBox( boxVector );
689    
690     sprintf( simnfo->sampleName, "%s.dump", bsInfo.outPrefix );
691     sprintf( simnfo->finalName, "%s.init", bsInfo.outPrefix );
692    
693     simnfo->atoms = atoms;
694    
695     // set up the writer and write out
696    
697     writer = new DumpWriter( simnfo );
698     writer->writeFinal(0.0);
699    
700     // clean up the memory
701    
702     if( molMap != NULL ) delete[] molMap;
703     if( cardDeck != NULL ) delete[] cardDeck;
704     if( locate != NULL ){
705     for(i=0; i<bsInfo.nComponents; i++){
706     delete locate[i];
707     }
708     delete[] locate;
709     }
710     if( atoms != NULL ){
711     for(i=0; i<nAtoms; i++){
712     delete atoms[i];
713     }
714     Atom::destroyArrays();
715     delete[] atoms;
716     }
717     if( molSeq != NULL ) delete[] molSeq;
718     if( simnfo != NULL ) delete simnfo;
719     if( writer != NULL ) delete writer;
720    
721     return 1;
722     }
723    
724    
725     void getRandomRot( double rot[3][3] ){
726    
727     double theta, phi, psi;
728     double cosTheta;
729    
730     // select random phi, psi, and cosTheta
731    
732     phi = 2.0 * M_PI * drand48();
733     psi = 2.0 * M_PI * drand48();
734     cosTheta = (2.0 * drand48()) - 1.0; // sample cos -1 to 1
735    
736     theta = acos( cosTheta );
737    
738     rot[0][0] = (cos(phi) * cos(psi)) - (sin(phi) * cos(theta) * sin(psi));
739     rot[0][1] = (sin(phi) * cos(psi)) + (cos(phi) * cos(theta) * sin(psi));
740     rot[0][2] = sin(theta) * sin(psi);
741    
742     rot[1][0] = -(cos(phi) * sin(psi)) - (sin(phi) * cos(theta) * cos(psi));
743     rot[1][1] = -(sin(phi) * sin(psi)) + (cos(phi) * cos(theta) * cos(psi));
744     rot[1][2] = sin(theta) * cos(psi);
745    
746     rot[2][0] = sin(phi) * sin(theta);
747     rot[2][1] = -cos(phi) * sin(theta);
748     rot[2][2] = cos(theta);
749     }
750    
751    
752    
753     void buildMap( double &x, double &y, double &z,
754     double boxX, double boxY, double boxZ ){
755    
756     if(x < 0) x -= boxX * (double)( (int)( (x / boxX) - 0.5 ) );
757     else x -= boxX * (double)( (int)( (x / boxX ) + 0.5));
758    
759     if(y < 0) y -= boxY * (double)( (int)( (y / boxY) - 0.5 ) );
760     else y -= boxY * (double)( (int)( (y / boxY ) + 0.5));
761    
762     if(z < 0) z -= boxZ * (double)( (int)( (z / boxZ) - 0.5 ) );
763     else z -= boxZ * (double)( (int)( (z / boxZ ) + 0.5));
764     }