ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/utils/nanoBuilder.cpp
Revision: 598
Committed: Mon Jul 14 21:35:45 2003 UTC (21 years, 2 months ago) by chuckv
File size: 14988 byte(s)
Log Message:
added a nanoSysBuilder that takes different cmd line arguments.

File Contents

# User Rev Content
1 chuckv 589 #include <iostream>
2    
3     #include <cstdlib>
4     #include <cstring>
5     #include <cmath>
6     #include <vector>
7    
8     #include "simError.h"
9     #include "SimInfo.hpp"
10     #include "ReadWrite.hpp"
11    
12     #include "latticeBuilder.hpp"
13     #include "MoLocator.hpp"
14     #include "sysBuild.hpp"
15     #include "nanoBuilder.hpp"
16    
17 chuckv 598 nanoBuilder::nanoBuilder(int &hasError){
18 chuckv 589 int Errors;
19     int foundCore,foundShell;
20     int i;
21 gezelter 592
22 chuckv 589 //Zero variables
23     particleRadius = 0.0;
24     coreRadius = 0.0;
25     vacancyFraction = 0.0;
26     vacancyRadius = 0.0;
27     shellRadius = 0.0;
28     latticeSpacing = 0.0;
29    
30     buildNmol = 0;
31    
32     nCoreMolecules = 0;
33     nShellMolecules = 0;
34    
35     atomCount = 0;
36     coreAtomCount = 0;
37     shellAtomCount = 0;
38    
39    
40    
41     moleculeCount = 0;
42     foundCore = 0;
43     foundShell = 0;
44     totalMolecules = 0;
45     coreHasOrientation = 0;
46     shellHasOrientation = 0;
47     nInterface = 0;
48     nMol = 0;
49    
50     hasError = 0;
51     Errors = 0;
52 chuckv 598
53     //Initialize class members from bsInfo struct that sysbuilder provides.
54     isRandom = bsInfo.isRandomParticle;
55     hasVacancies = bsInfo.hasVacancies;
56     latticeType = bsInfo.latticeType;
57     particleRadius = bsInfo.particleRadius;
58     coreRadius = bsInfo.coreRadius;
59     vacancyFraction = bsInfo.vacancyFraction;
60     latticeSpacing = bsInfo.latticeSpacing;
61     soluteX = bsInfo.soluteX; //Mole fraction for random particle.
62 chuckv 589
63    
64    
65    
66    
67     for (i=0;bsInfo.nComponents;i++){
68     if( !strcmp( bsInfo.compStamps[i]->getID(),bsInfo.coreName )){
69     foundCore = 1;
70     coreStamp = bsInfo.compStamps[i];
71     nCoreMolecules = bsInfo.componentsNmol[i];
72     }
73     if( !strcmp( bsInfo.compStamps[i]->getID(),bsInfo.shellName)){
74     foundShell = 1;
75     shellStamp = bsInfo.compStamps[i];
76     nShellMolecules = bsInfo.componentsNmol[i];
77    
78     }
79    
80     }
81    
82    
83    
84     if( !foundCore ){
85     hasError = 1;
86     return;
87     }
88     if( !foundShell ){
89     hasError = 1;
90     return;
91     }
92    
93    
94    
95     Errors = sanityCheck();
96    
97     if (Errors){
98     hasError = 1;
99     return;
100     }
101    
102    
103    
104    
105    
106    
107    
108     nCoreModelAtoms = coreStamp->getNAtoms();
109     nShellModelAtoms = shellStamp->getNAtoms();
110    
111    
112     // We assume that if the core or shell model has more then one atom
113     // the model has an orientational component...
114     if (nCoreModelAtoms > 1) coreHasOrientation = 1;
115     if (nShellModelAtoms > 1) shellHasOrientation = 1;
116    
117     maxModelNatoms = std::max(nCoreModelAtoms,nShellModelAtoms);
118    
119     /* If we specify a number of atoms in bass, we will try to build a nanopartice
120     with that number.
121     */
122    
123    
124     if ((nShellMolecules != 0) && (nCoreMolecules != 0)){
125     totalMolecules = nShellMolecules + nCoreMolecules;
126     nCells = ceil(pow((double)totalMolecules/4.0, 1/3));
127     buildNmol = 1;
128     }
129     else {
130     nCells = 2.0 * particleRadius/latticeSpacing;
131     shellRadius = particleRadius - coreRadius;
132     }
133    
134    
135    
136    
137     // Initialize random seed
138     srand48( RAND_SEED );
139    
140    
141     }
142    
143    
144     nanoBuilder::~nanoBuilder(){
145     }
146    
147    
148     // Checks to make sure we aren't doing something the builder can't do.
149     int nanoBuilder::sanityCheck(void){
150    
151     // Right now we only do bimetallic nanoparticles
152     if (bsInfo.nComponents > 2) return 1;
153    
154     //Check for vacancies and random
155     if (hasVacancies && isRandom) return 1;
156    
157     // make sure we aren't trying to build a core larger then the total particle size
158     if ((coreRadius >= particleRadius) && (particleRadius != 0)) return 1;
159    
160     // we initialize the lattice spacing to be 0.0, if the lattice spacing is still 0.0
161     // we have a problem
162     if (latticeSpacing == 0.0) return 1;
163    
164     // Check to see if we are specifing the number of atoms in the particle correctly.
165     if ((nShellMolecules == 0) && (nCoreMolecules != 0)){
166     cerr << "nShellParticles is zero and nCoreParticles != 0" << "\n";
167     return 1;
168     }
169     // Make sure there are more then two components if we are building a randomly mixed particle.
170     if ((bsInfo.nComponents < 2) && (isRandom)){
171     cerr << "Two Components are needed to build a random particle." << "\n";
172     }
173     // Make sure both the core and shell models specify a target nmol.
174     if ((nShellMolecules != 0) && (nCoreMolecules == 0)){
175     cerr << "nCoreParticles is zero and nShellParticles != 0" << "\n";
176     return 1;
177     }
178    
179     return 0;
180    
181     }
182    
183    
184    
185     int nanoBuilder::buildNanoParticle( void ){
186    
187     int ix;
188     int iy;
189     int iz;
190     double *rx;
191     double *ry;
192     double *rz;
193     double pos[3];
194     double A[3][3];
195 gezelter 592 double HmatI[3][3];
196 chuckv 589
197     int nCellSites;
198     int iref;
199     int appNMols;
200     int latticeCount = 0;
201    
202     int nAtoms;
203     int nCoreAtomCounter = 0;
204     int nShellAtomCounter = 0;
205     int hasError;
206    
207 gezelter 592 int i, j;
208 chuckv 589
209     int interfaceIndex = 0;
210     double dist;
211     double distsq;
212     int latticeNpoints;
213     int shesActualSizetoMe = 0;
214    
215     DumpWriter* writer;
216     SimInfo* simnfo;
217    
218 gezelter 592 Lattice *myLattice;
219     MoLocator *coreLocate;
220     MoLocator *shellLocate;
221 chuckv 589
222    
223     Atom** atoms;
224    
225     hasError = 0;
226    
227     myLattice = new Lattice(FCC_LATTICE_TYPE,latticeSpacing);
228     /*
229     latticeNpoints = myLattice.getNpoints();
230    
231     // Initializd atom vector to approximate size.
232     switch (buildType){
233    
234     case BUILD_NMOL_PARTICLE:
235    
236     break;
237     case BUILD_CORE_SHELL_VACANCY:
238     // Make space in the vector for all atoms except the last full cells
239     // We will have to add at most (latticeNpoints-1)^3 to vector
240     appNMols = latticeNPoints * pow((double)(nCells - 1),3);
241     moleculeVector.pushBack();
242    
243     default:
244     // Make space in the vector for all atoms except the last full cells
245     // We will have to add at most (latticeNpoints-1)^3 to vector
246     appNMols = latticeNPoints * pow((double)(nCells - 1),3);
247    
248     }
249     */
250    
251    
252    
253    
254     // Create molocator and atom arrays.
255     coreLocate = new MoLocator(coreStamp);
256     shellLocate = new MoLocator(shellStamp);
257    
258    
259    
260    
261    
262    
263     for(iz=-nCells;iz < nCells;iz++){
264     for(iy=-nCells;iy<nCells;iy++){
265     for(ix=-nCells;ix<nCells;ix++){
266     nCellSites = myLattice->getLatticePoints(&rx,&ry,&rz,
267     ix,iy,iz);
268     for (iref=1;iref<nCellSites;iref++){
269     latticeCount++;
270    
271     pos[0] = rx[iref];
272     pos[1] = ry[iref];
273     pos[2] = rz[iref];
274    
275     distsq = rx[iref]*rx[iref] + ry[iref]*ry[iref] +rz[iref]*rz[iref];
276     dist = sqrt(distsq);
277    
278     switch(buildType){
279    
280     case BUILD_CORE_SHELL:
281     nanoBuilder::buildWithCoreShell(dist,pos);
282     break;
283     case BUILD_CORE_SHELL_VACANCY:
284     nanoBuilder::buildWithVacancies(dist,pos);
285     break;
286    
287     case BUILD_RANDOM_PARTICLE:
288     nanoBuilder::buildRandomlyMixed(dist,pos);
289     break;
290     case BUILD_NMOL_PARTICLE:
291     nanoBuilder::buildNmolParticle(dist,pos);
292     }
293     }
294     }
295     }
296     }
297    
298    
299    
300     // Create vacancies
301     if (hasVacancies) buildVacancies();
302    
303     // Find the size of the atom vector not including Null atoms
304     for (i=0;i<moleculeVector.size();i++){
305     if (! moleculeVector[i].isVacancy){
306     shesActualSizetoMe++;
307     nAtoms = moleculeVector[i].myStamp->getNAtoms();
308     }
309     }
310    
311     // Make a random particle.
312     if (isRandom){
313     placeRandom(shesActualSizetoMe);
314    
315     // Loop back thru and count natoms since they may have changed
316     for (i=0;i<moleculeVector.size();i++){
317     if (! moleculeVector[i].isVacancy){
318     shesActualSizetoMe++;
319     nAtoms = moleculeVector[i].myStamp->getNAtoms();
320     }
321     }
322     }
323    
324    
325     Atom::createArrays( nAtoms );
326     atoms = new Atom*[nAtoms];
327    
328    
329    
330     shesActualSizetoMe = 0;
331     /* Use the information from the molecule vector to place the atoms.
332     */
333     for (i= 0;i<moleculeVector.size();i++){
334     if (! moleculeVector[i].isVacancy) {
335     orientationMunger( A );
336     if( moleculeVector[i].isCore){
337 chuckv 598 nCoreAtomCounter += nCoreModelAtoms;
338 chuckv 589 coreLocate->placeMol(moleculeVector[i].pos,A,atoms,nShellAtomCounter);
339     }
340     else {
341 chuckv 598 nShellAtomCounter += nShellModelAtoms;
342 chuckv 589 shellLocate->placeMol(moleculeVector[i].pos,A,atoms,nCoreAtomCounter);
343     }
344     shesActualSizetoMe++;
345     }
346     }
347    
348    
349     // shellLocate.placeMol(pos, A, moleculeVector,shellAtomCount);
350    
351 gezelter 592 for (i=0;i<3;i++)
352     for (j=0; j<3; j++)
353     simnfo->Hmat[i][j] = 0.0;
354 chuckv 589
355 gezelter 592 simnfo->Hmat[0][0] = 1.0;
356     simnfo->Hmat[1][1] = 1.0;
357     simnfo->Hmat[2][2] = 1.0;
358    
359 chuckv 589 // set up the SimInfo object
360 gezelter 592
361 chuckv 589 simnfo = new SimInfo();
362     simnfo->n_atoms = nAtoms;
363    
364     sprintf( simnfo->sampleName, "%s.dump", bsInfo.outPrefix );
365     sprintf( simnfo->finalName, "%s.init", bsInfo.outPrefix );
366    
367     simnfo->atoms = atoms;
368    
369     // set up the writer and write out
370    
371     writer = new DumpWriter( simnfo );
372     writer->writeFinal(0.0);
373    
374     // clean up
375    
376     delete[] myLattice;
377    
378     return hasError;
379     }
380    
381     // Begin Builder routines------------------------------->
382    
383     /* Builds a standard core-shell nanoparticle.
384     */
385     void nanoBuilder::buildWithCoreShell(double dist, double pos[3]){
386    
387    
388     if ( dist <= particleRadius ){
389     moleculeVector.push_back(myMol);
390    
391     if (dist <= coreRadius){
392 chuckv 598 coreAtomCount += nCoreModelAtoms;
393 chuckv 589 moleculeVector[moleculeCount].pos[0] = pos[0];
394     moleculeVector[moleculeCount].pos[1] = pos[1];
395     moleculeVector[moleculeCount].pos[2] = pos[2];
396     moleculeVector[moleculeCount].myStamp = coreStamp;
397     moleculeVector[moleculeCount].isCore = 1;
398     moleculeVector[moleculeCount].isShell = 0;
399    
400     }
401     // Place shell
402     else{
403 chuckv 598 shellAtomCount += nShellModelAtoms;
404 chuckv 589 moleculeVector[moleculeCount].pos[0] = pos[0];
405     moleculeVector[moleculeCount].pos[1] = pos[1];
406     moleculeVector[moleculeCount].pos[2] = pos[2];
407     moleculeVector[moleculeCount].myStamp = shellStamp;
408     moleculeVector[moleculeCount].isCore = 0;
409     moleculeVector[moleculeCount].isShell = 1;
410    
411     }
412     moleculeCount++;
413     }
414    
415     }
416     /*
417     Builds a core-shell nanoparticle and tracks the number of molecules at the
418     interface between the core-shell. These are recorded in vacancyInterface which is just
419     an integer vector.
420     */
421     void nanoBuilder::buildWithVacancies(double dist, double pos[3]){
422     if ( dist <= particleRadius ){
423    
424     moleculeVector.push_back(myMol);
425     if (dist <= coreRadius){
426    
427 chuckv 598 coreAtomCount += nCoreModelAtoms;
428 chuckv 589 moleculeVector[moleculeCount].pos[0] = pos[0];
429     moleculeVector[moleculeCount].pos[1] = pos[1];
430     moleculeVector[moleculeCount].pos[2] = pos[2];
431     moleculeVector[moleculeCount].myStamp = coreStamp;
432     moleculeVector[moleculeCount].isCore = 1;
433     moleculeVector[moleculeCount].isShell = 0;
434    
435     if ((dist >= coreRadius - vacancyRadius/2.0) &&
436     (dist <= coreRadius + vacancyRadius/2.0)){
437    
438     vacancyInterface.push_back(moleculeCount);
439     nInterface++;
440     }
441     } else {
442     // Place shell
443 chuckv 598 shellAtomCount += nShellModelAtoms;
444 chuckv 589 moleculeVector[moleculeCount].pos[0] = pos[0];
445     moleculeVector[moleculeCount].pos[1] = pos[1];
446     moleculeVector[moleculeCount].pos[2] = pos[2];
447     moleculeVector[moleculeCount].myStamp = shellStamp;
448     moleculeVector[moleculeCount].isCore = 0;
449     moleculeVector[moleculeCount].isShell = 1;
450    
451     }
452     moleculeCount++;
453     }
454    
455    
456    
457     }
458    
459     /* Builds a core-shell nanoparticle where the number of core and shell
460     molecules is known.
461     */
462     void nanoBuilder::buildNmolParticle(double dist, double pos[3]){
463     static int nMolCounter = 0;
464     static int nCoreMolCounter = 0;
465    
466    
467     if (nMolCounter < totalMolecules){
468     moleculeVector.push_back(myMol);
469     if (nCoreMolCounter < nCoreMolecules){
470    
471 chuckv 598 coreAtomCount += nCoreModelAtoms;
472 chuckv 589 moleculeVector[moleculeCount].pos[0] = pos[0];
473     moleculeVector[moleculeCount].pos[1] = pos[1];
474     moleculeVector[moleculeCount].pos[2] = pos[2];
475     moleculeVector[moleculeCount].myStamp = coreStamp;
476     moleculeVector[moleculeCount].isCore = 1;
477     moleculeVector[moleculeCount].isShell = 0;
478    
479    
480     } else {
481 chuckv 598 shellAtomCount += nShellModelAtoms;
482 chuckv 589 moleculeVector[moleculeCount].pos[0] = pos[0];
483     moleculeVector[moleculeCount].pos[1] = pos[1];
484     moleculeVector[moleculeCount].pos[2] = pos[2];
485     moleculeVector[moleculeCount].myStamp = shellStamp;
486     moleculeVector[moleculeCount].isCore = 0;
487     moleculeVector[moleculeCount].isShell = 1;
488    
489    
490     }
491    
492     }
493     }
494    
495    
496     /* Builds a randomly mixed nanoparticle. We build the particle to be
497     entirely the core model, then randomly switch identities after the particle is built.
498     */
499     void nanoBuilder::buildRandomlyMixed(double dist, double pos[3]){
500    
501    
502     if ( dist <= particleRadius ){
503     moleculeCount++;
504    
505    
506     moleculeVector[moleculeCount].pos[0] = pos[0];
507     moleculeVector[moleculeCount].pos[1] = pos[1];
508     moleculeVector[moleculeCount].pos[2] = pos[2];
509     moleculeVector[moleculeCount].myStamp = coreStamp;
510     moleculeVector[moleculeCount].isCore = 1;
511     moleculeVector[moleculeCount].isShell = 0;
512    
513     }
514    
515    
516    
517     }
518    
519    
520     // -----------------------END Builder routines.
521    
522    
523    
524     //------------------------Begin Helper routines.
525     void nanoBuilder::placeRandom(int totalMol){
526     int nSolute;
527     int nSolvent;
528     int i;
529     int notfound;
530     double solute_x;
531     double solvent_x;
532    
533     int tester;
534    
535     nSolute = floor(soluteX * (double)totalMolecules); //CHECK ME
536     nSolvent = totalMolecules - nSolute;
537    
538     solute_x = (double)nSolute/(double)totalMolecules;
539     solvent_x = 1.0 - solute_x;
540    
541    
542    
543    
544     for(i=0;nSolute-1;i++){
545     notfound = 1;
546    
547     while(notfound){
548    
549     tester = floor((double)totalMolecules * drand48()); //Pick a molecule
550    
551     if (moleculeVector[tester].isCore){ // Make sure we select a core atom to change
552    
553     moleculeVector[tester].isCore = 0;
554     moleculeVector[tester].isShell = 1;
555     moleculeVector[tester].myStamp = shellStamp;
556     notfound = 0; //set notfound = false.
557     }
558    
559     }
560    
561     }
562     }
563    
564    
565     void nanoBuilder::buildVacancies(void){
566     int i;
567     int* VacancyList; //logical nInterface long.
568     int notfound;
569     int index = 0;
570     int nVacancies;
571     int tester;
572    
573     if (nInterface != 0){
574     nVacancies = floor((double)nInterface * vacancyFraction);
575    
576     VacancyList = new int[nInterface];
577    
578     // make vacancy list all false
579     for(i=0;i<nInterface-1;i++){
580     VacancyList[i] = 0;
581     }
582    
583     // Build a vacancy list....
584     for(i=0;nVacancies-1;i++){
585     notfound = 1;
586     while(notfound){
587    
588     tester = floor((double)nInterface * drand48());
589    
590     if(! VacancyList[tester]){
591     VacancyList[tester] = 1;
592     notfound = 0;
593     }
594    
595     }
596     }
597     }
598     // Loop through and kill the vacancies from atom vector.
599    
600     for (i=0;i<nInterface;i++){
601     if (VacancyList[i]){
602     moleculeVector[vacancyInterface[i]].isVacancy = 1;
603     } // End Vacancy List
604     } // for nInterface
605    
606    
607     delete[] VacancyList;
608     }
609    
610    
611    
612    
613     void nanoBuilder::orientationMunger(double rot[3][3]){
614    
615     double theta, phi, psi;
616     double cosTheta;
617    
618     // select random phi, psi, and cosTheta
619    
620     phi = 2.0 * M_PI * drand48();
621     psi = 2.0 * M_PI * drand48();
622     cosTheta = (2.0 * drand48()) - 1.0; // sample cos -1 to 1
623    
624     theta = acos( cosTheta );
625    
626     rot[0][0] = (cos(phi) * cos(psi)) - (sin(phi) * cos(theta) * sin(psi));
627     rot[0][1] = (sin(phi) * cos(psi)) + (cos(phi) * cos(theta) * sin(psi));
628     rot[0][2] = sin(theta) * sin(psi);
629    
630     rot[1][0] = -(cos(phi) * sin(psi)) - (sin(phi) * cos(theta) * cos(psi));
631     rot[1][1] = -(sin(phi) * sin(psi)) + (cos(phi) * cos(theta) * cos(psi));
632     rot[1][2] = sin(theta) * cos(psi);
633    
634     rot[2][0] = sin(phi) * sin(theta);
635     rot[2][1] = -cos(phi) * sin(theta);
636     rot[2][2] = cos(theta);
637    
638     }
639    
640    
641    
642    
643    
644    
645