Detector::Detector(int nx, int ny, float_tt resX, float_tt resY) : error(0), shiftX(0), shiftY(0), Navg(0), thickness(0) { #if FLOAT_PRECISION == 1 image = float2D(nx,ny,"ADFimag"); image2 = float2D(nx,ny,"ADFimag"); #else image = double2D(nx,ny,"ADFimag"); image2 = double2D(nx,ny,"ADFimag"); #endif m_imageIO=ImageIOPtr(new CImageIO(nx, ny, thickness, resX, resY, std::vector<double>(2+nx*ny), "STEM image")); }
WAVEFUNC::WAVEFUNC(int x, int y, float_tt resX, float_tt resY) : detPosX(0), detPosY(0), iPosX(0), iPosY(0), thickness(0.0), nx(x), ny(y), resolutionX(resX), resolutionY(resY) { char waveFile[256]; const char *waveFileBase = "mulswav"; #if FLOAT_PRECISION == 1 diffpat = float2D(nx,ny,"diffpat"); avgArray = float2D(nx,ny,"avgArray"); #else diffpat = double2D(nx,ny,"diffpat"); avgArray = double2D(nx,ny,"avgArray"); #endif m_imageIO=ImageIOPtr(new CImageIO(nx, ny, thickness, resolutionX, resolutionY)); #if FLOAT_PRECISION == 1 wave = complex2Df(nx, ny, "wave"); fftPlanWaveForw = fftwf_plan_dft_2d(nx,ny,wave[0],wave[0],FFTW_FORWARD, FFTW_ESTIMATE); fftPlanWaveInv = fftwf_plan_dft_2d(nx,ny,wave[0],wave[0],FFTW_BACKWARD, FFTW_ESTIMATE); #else wave = complex2D(nx, ny, "wave"); fftPlanWaveForw = fftw_plan_dft_2d(nx,ny,wave[0],wave[0],FFTW_FORWARD, fftMeasureFlag); fftPlanWaveInv = fftw_plan_dft_2d(nx,ny,wave[0],wave[0],FFTW_BACKWARD, fftMeasureFlag); #endif sprintf(waveFile,"%s.img",waveFileBase); strcpy(fileout,waveFile); sprintf(fileStart,"mulswav.img"); }
/***************************************************************** * Create the amorphous part of the model ****************************************************************/ void makeAmorphous() { int g,p,iatom,ix,iy,iz,ic,atomCount = 0,amorphSites,amorphAtoms; static double *axCell,*byCell,*czCell=NULL; static double **Mm = NULL; double rCellx,rCelly,rCellz; double d,r; atom *amorphCell; // atom newAtom; // double xpos,ypos,zpos; int nx,ny,nz; int *randArray,randCount; if (Mm == NULL) { Mm = double2D(3,3,"Mm"); axCell=Mm[0]; byCell=Mm[1]; czCell=Mm[2]; } for (g=0;g<nGrains;g++) { /******************************************************** * if this grain is an amorphous one ... */ if (grains[g].amorphFlag == AMORPHOUS) { r = grains[g].rmin/grains[g].rFactor; /* create an hexagonally closed packed unit cell for initial amorphous structure * The length of each vector is now 1 */ axCell[0] = r; axCell[1] = 0; axCell[2] = 0; byCell[0] = 0.5*r; byCell[1] = 0.5*sqrt(3.0)*r; byCell[2] = 0; czCell[0] = 0.5*r; czCell[1] = 0.5/sqrt(3.0)*r; czCell[2] = sqrt(5.0)/6*r; /* size of rectangular cell containing 4 atoms: */ rCellx = r; rCelly = sqrt(3.0)*r; rCellz = (sqrt(5.0)*r)/3.0; /* determine number of unit cells in super cell */ nx = (int)(superCell.ax/rCellx); ny = (int)(superCell.by/rCelly); nz = (int)(superCell.cz/rCellz); amorphSites = 4*nx*ny*nz; amorphCell = (atom *)malloc((amorphSites+1)*sizeof(atom)); atomCount = 0; for (ix=0;ix<=nx;ix++) { for (iy=0;iy<=ny;iy++) { for (iz=0;iz<=nz;iz++) { for (ic=0;ic<4;ic++) { /* check if this atom and any of the 4 atoms per rect. unit cell lie within the super cell */ amorphCell[atomCount].x = ix*rCellx-(ic==3)*axCell[0]+(ic % 2)*byCell[0]+(ic>1)*czCell[0]; amorphCell[atomCount].y = iy*rCelly-(ic==3)*axCell[1]+(ic % 2)*byCell[1]+(ic>1)*czCell[1]; amorphCell[atomCount].z = iz*rCellz-(ic==3)*axCell[2]+(ic % 2)*byCell[2]+(ic>1)*czCell[2]; if ((amorphCell[atomCount].x >= 0) && (amorphCell[atomCount].x < superCell.ax) && (amorphCell[atomCount].y >= 0) && (amorphCell[atomCount].y < superCell.by) && (amorphCell[atomCount].z >= 0) && (amorphCell[atomCount].z < superCell.cz)) { for (p=0;p<grains[g].nplanes;p++) { d = findLambda(grains[g].planes+p,&(amorphCell[atomCount].z),-1); if (d < 0) break; } /* if all the previous test have been successful, this atom is IN */ if (p == grains[g].nplanes) atomCount++; } } /* ic ... */ } /* iz ... */ } /* iy ... */ } /* ix ... */ amorphSites = atomCount; /**************************************************************************************** * Now we have all the sites within the bounding planes on which we can put atoms */ /* the true number of amorphous atoms is # of sites / rFactor^3 */ amorphAtoms = (int)floor((double)amorphSites/pow(grains[g].rFactor,3.0)); if (amorphAtoms > amorphSites) amorphAtoms = amorphSites; randCount = amorphSites; atomCount = superCell.natoms; superCell.atoms = (atom *)realloc(superCell.atoms,(atomCount+amorphAtoms+1)*sizeof(atom)); if (superCell.atoms == NULL) { printf("makeAmorphous: Could not allocate memory for additional atoms!\n"); exit(0); } randArray = (int *)malloc(amorphSites*sizeof(int)); for (ix=0;ix<amorphSites;ix++) randArray[ix] = ix; /* printf("memory allocation: sC.atoms: %d .. %d, rArray: %d .. %d\n", (int)superCell.atoms,(int)superCell.atoms+(atomCount+amorphAtoms+1)*sizeof(atom), (int)randArray,(int)randArray+amorphSites*sizeof(int)); */ for (ix=amorphAtoms;ix>0;ix--) { do { iy = (int)((double)rand()*(double)(randCount-1)/(double)(RAND_MAX)); if (iy >= randCount) iy = randCount-1; if (iy < 0) iy = 0; // printf("%5d, iy: %d, sites: %d, atoms: %d ",ix,iy,randCount,amorphAtoms); iz = randArray[iy]; if (iz > amorphSites) { printf("%5d, iy: %d, sites: %d, atoms: %d ",ix,iy,randCount,amorphAtoms); printf("iz: %d (%d)\n",iz,(int)superCell.atoms[atomCount].z); printf("makeAmorphous: Error because of overlapping memory areas!\n"); for (iz=0;iz<=amorphAtoms;iz++) printf("iz=%d: %d\n",iz,randArray[iz]); exit(0); } } while (iz > amorphSites); /* replace already choosen sites with unused ones, so that we don't occupy * any site twice */ if (iy == randCount-1) randCount--; else randArray[iy] = randArray[--randCount]; iatom = ix % grains[g].natoms; superCell.atoms[atomCount].q = grains[g].unitCell[iatom].q; superCell.atoms[atomCount].dw = grains[g].unitCell[iatom].dw; superCell.atoms[atomCount].occ = grains[g].unitCell[iatom].occ; superCell.atoms[atomCount].Znum = grains[g].unitCell[iatom].Znum; superCell.atoms[atomCount].x = amorphCell[iz].x; superCell.atoms[atomCount].y = amorphCell[iz].y; superCell.atoms[atomCount].z = amorphCell[iz].z; atomCount++; } superCell.natoms = atomCount; free(randArray); free(amorphCell); } /* end of if amorph,i.e. crystalline */ } /* g=0..nGrains .. */ }
/******************************************************************** * This function adds only the crystalline atoms to the superCell * the amorphous ones are handled by makeAmorphous, and makeSpecial ********************************************************************/ void makeSuperCell() { int g,p,iatom,ix,iy,iz,atomCount = 0; // atom *atomPtr; // atomPtr = (atom *)malloc(sizeof(atom)); static double *axCell,*byCell,*czCell=NULL; static double **Mm = NULL, **Mminv = NULL, **Mrot = NULL,**Mr=NULL,**Mr2=NULL; static double **a = NULL,**b= NULL; double maxLength,dx,dy,dz,d,dxs,dys,dzs; atom newAtom; // double xpos,ypos,zpos; int nxmin,nxmax,nymin,nymax,nzmin,nzmax; /* claculate maximum length in supercell box, which is naturally * the room diagonal: */ maxLength = vectLength(&(superCell.ax)); /* maxLength = sqrt(superCell.ax*superCell.ax+ superCell.by*superCell.by+ superCell.cz*superCell.cz); */ if (Mm == NULL) { Mm = double2D(3,3,"Mm"); Mminv = double2D(3,3,"Mminv"); Mrot = double2D(3,3,"Mrot"); Mr = double2D(3,3,"Mr"); Mr2 = double2D(3,3,"Mr"); axCell=Mm[0]; byCell=Mm[1]; czCell=Mm[2]; a = double2D(1,3,"a"); b = double2D(1,3,"b"); } atomCount = superCell.natoms; for (g=0;g<nGrains;g++) { /******************************************************** * if this grain is a crystalline one ... */ if (grains[g].amorphFlag == 0) { dx = grains[g].shiftx/superCell.ax; dy = grains[g].shifty/superCell.by; dz = grains[g].shiftz/superCell.cz; /* find the rotated unit cell vectors .. */ makeCellVect(grains+g, axCell, byCell, czCell); // showMatrix(Mm,3,3,"M"); /////////////////////////////////////////////////////////////////// memset(Mrot[0],0,3*3*sizeof(double)); Mrot[0][0] = 1.0; Mrot[1][1] = 1.0; Mrot[2][2] = 1.0; memcpy(Mr2[0],Mrot[0],3*3*sizeof(double)); memset(Mr[0],0,3*3*sizeof(double)); Mr[0][0] = 1.0; Mr[1][1] = cos(grains[g].tiltx); Mr[1][2] = sin(grains[g].tiltx); Mr[2][1] = -sin(grains[g].tiltx); Mr[2][2] = cos(grains[g].tiltx); matrixProduct(Mrot,3,3,Mr,3,3,Mr2); memcpy(Mrot[0],Mr2[0],3*3*sizeof(double)); // showMatrix(Mrot,3,3,"Mrotx"); memset(Mr[0],0,3*3*sizeof(double)); Mr[1][1] = 1.0; Mr[0][0] = cos(grains[g].tilty); Mr[0][2] = -sin(grains[g].tilty); Mr[2][0] = sin(grains[g].tilty); Mr[2][2] = cos(grains[g].tilty); matrixProduct(Mrot,3,3,Mr,3,3,Mr2); memcpy(Mrot[0],Mr2[0],3*3*sizeof(double)); // showMatrix(Mrot,3,3,"Mrotxy"); memset(Mr[0],0,3*3*sizeof(double)); Mr[2][2] = 1.0; Mr[0][0] = cos(grains[g].tiltz); Mr[0][1] = sin(grains[g].tiltz); Mr[1][0] = -sin(grains[g].tiltz); Mr[1][1] = cos(grains[g].tiltz); matrixProduct(Mrot,3,3,Mr,3,3,Mr2); memcpy(Mrot[0],Mr2[0],3*3*sizeof(double)); // showMatrix(Mrot,3,3,"Mrotxyz"); /////////////////////////////////////////////////////////////////// /* rotateVect(axCell,axCell,grains[g].tiltx,grains[g].tilty,grains[g].tiltz); rotateVect(byCell,byCell,grains[g].tiltx,grains[g].tilty,grains[g].tiltz); rotateVect(czCell,czCell,grains[g].tiltx,grains[g].tilty,grains[g].tiltz); */ inverse_3x3(Mminv[0],Mm[0]); matrixProduct(Mm,3,3,Mrot,3,3,Mr2); memcpy(Mm[0],Mr2[0],3*3*sizeof(double)); // showMatrix(Mm,3,3,"M"); inverse_3x3(Mr2[0],Mm[0]); /* find out how far we will have to go in units of unit cell vectors. * when creating the supercell by checking the number of unit cell vectors * necessary to reach every corner of the supercell box. */ memset(a[0],0,3*sizeof(double)); matrixProduct(a,1,3,Mr2,3,3,b); // showMatrix(Mm,3,3,"M"); // showMatrix(Mminv,3,3,"M"); nxmin = nxmax = (int)floor(b[0][0]-dx); nymin = nymax = (int)floor(b[0][1]-dy); nzmin = nzmax = (int)floor(b[0][2]-dz); for (ix=0;ix<=1;ix++) for (iy=0;iy<=1;iy++) for (iz=0;iz<=1;iz++) { a[0][0]=ix*superCell.ax; a[0][1]=iy*superCell.by; a[0][2]=iz*superCell.cz; matrixProduct(a,1,3,Mr2,3,3,b); // showMatrix(b,1,3,"b"); if (nxmin > (int)floor(b[0][0]-dx)) nxmin=(int)floor(b[0][0]-dx); if (nxmax < (int)ceil( b[0][0]-dx)) nxmax=(int)ceil( b[0][0]-dx); if (nymin > (int)floor(b[0][1]-dy)) nymin=(int)floor(b[0][1]-dy); if (nymax < (int)ceil( b[0][1]-dy)) nymax=(int)ceil( b[0][1]-dy); if (nzmin > (int)floor(b[0][2]-dz)) nzmin=(int)floor(b[0][2]-dz); if (nzmax < (int)ceil( b[0][2]-dz)) nzmax=(int)ceil( b[0][2]-dz); } // nxmin--;nxmax++;nymin--;nymax++;nzmin--;nzmax++; superCell.atoms = (atom *)realloc(superCell.atoms,(superCell.natoms+1+ (nxmax-nxmin)*(nymax-nymin)* (nzmax-nzmin)*grains[g].natoms)* sizeof(atom)); // showMatrix(Mm,3,3,"Mm"); // showMatrix(Mminv,3,3,"Mminv"); printf("Grain %d: range: (%d..%d, %d..%d, %d..%d)\n", g,nxmin,nxmax,nymin,nymax,nzmin,nzmax); dx = grains[g].shiftx; dy = grains[g].shifty; dz = grains[g].shiftz; for (iatom=0;iatom<grains[g].natoms;iatom++) { memcpy(&newAtom,&(grains[g].unitCell[iatom]),sizeof(atom)); // We need to convert the cartesian coordinates of this atom // to fractional ones: b[0][0] = newAtom.x; b[0][1] = newAtom.y; b[0][2] = newAtom.z; matrixProduct(b,1,3,Mminv,3,3,a); newAtom.x = a[0][0]; newAtom.y = a[0][1]; newAtom.z = a[0][2]; //printf("%2d: %d (%g,%g,%g) (%g,%g,%g)\n",iatom,newAtom.Znum, // b[0][0],b[0][1],b[0][2],a[0][0],a[0][1],a[0][2]); for (ix=nxmin;ix<=nxmax;ix++) { for (iy=nymin;iy<=nymax;iy++) { for (iz=nzmin;iz<=nzmax;iz++) { /* atom position in reduced coordinates: */ // a[0][0] = ix+newAtom.x; a[0][1] = iy+newAtom.y; a[0][2] = iz+newAtom.z; a[0][0] = newAtom.x+ix; a[0][1] = newAtom.y+iy; a[0][2] = newAtom.z+iz; matrixProduct(a,1,3,Mm,3,3,b); /* b[0][0] = a[0][0]*Mm[0][0]+a[0][1]*Mm[0][1]+a[0][2]*Mm[0][2]; b[0][1] = a[0][0]*Mm[1][0]+a[0][1]*Mm[1][1]+a[0][2]*Mm[1][2]; b[0][2] = a[0][0]*Mm[2][0]+a[0][1]*Mm[2][1]+a[0][2]*Mm[2][2]; */ /* // same as matrixProduct: b[0][0] = a[0][0]*Mm[0][0]+a[0][1]*Mm[1][0]+a[0][2]*Mm[2][0]; b[0][1] = a[0][0]*Mm[0][1]+a[0][1]*Mm[1][1]+a[0][2]*Mm[2][1]; b[0][2] = a[0][0]*Mm[0][2]+a[0][1]*Mm[1][2]+a[0][2]*Mm[2][2]; */ superCell.atoms[atomCount].x = b[0][0]+dx; superCell.atoms[atomCount].y = b[0][1]+dy; superCell.atoms[atomCount].z = b[0][2]+dz; if ((superCell.atoms[atomCount].x >= 0) && (superCell.atoms[atomCount].x < superCell.ax) && (superCell.atoms[atomCount].y >= 0) && (superCell.atoms[atomCount].y < superCell.by) && (superCell.atoms[atomCount].z >= 0) && (superCell.atoms[atomCount].z < superCell.cz)) { // If this is a sphere: if (grains[g].sphereRadius > 0) { dxs = superCell.atoms[atomCount].x - grains[g].sphereX; dys = superCell.atoms[atomCount].y - grains[g].sphereY; dzs = superCell.atoms[atomCount].z - grains[g].sphereZ; if (dxs*dxs+dys*dys+dzs*dzs < grains[g].sphereRadius*grains[g].sphereRadius) { superCell.atoms[atomCount].dw = newAtom.dw; superCell.atoms[atomCount].occ = newAtom.occ; superCell.atoms[atomCount].q = newAtom.q; superCell.atoms[atomCount].Znum = newAtom.Znum; atomCount++; } } // If this is a straight-edged grain else { for (p=0;p<grains[g].nplanes;p++) { /* printf("hello %d (%g %g %g)\n",g, superCell.atoms[atomCount].x,superCell.atoms[atomCount].y, superCell.atoms[atomCount].z); */ d = findLambda(grains[g].planes+p,&(superCell.atoms[atomCount].z),-1); /* printf("%3d lambda: %g (%g %g %g), (%g %g %g), %d\n",atomCount,d, newAtom.x,newAtom.y,newAtom.z, superCell.atoms[atomCount].x,superCell.atoms[atomCount].y, superCell.atoms[atomCount].z,grains[g].nplanes); */ if (d < 0) break; } /* if all the previous test have been successful, this atom is IN, * which means that we also need to copy the other data elements * for this atom. */ if (p == grains[g].nplanes) { superCell.atoms[atomCount].q = newAtom.q; superCell.atoms[atomCount].dw = newAtom.dw; superCell.atoms[atomCount].occ = newAtom.occ; superCell.atoms[atomCount].Znum = newAtom.Znum; atomCount++; } } // if this is a sphere or not ... } } /* iz ... */ } /* iy ... */ } /* ix ... */ } /* iatom ... */ superCell.natoms = atomCount; } /* end of if !amorph,i.e. crystalline */ } /* g=0..nGrains .. */ /* atomPtr->x = 0.5; atomPtr->y = 0.2; atomPtr->z = 0.7; findLambda(grains[0].planes,&(atomPtr->z),1); */ }