libatomprobe
Library for Atom Probe Tomography (APT) computation
generate.cpp
Go to the documentation of this file.
1 /* generate.cpp : Crystal tiling functions
2  * Copyright (C) 2020 Daniel Haley
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
18 
19 namespace AtomProbe
20 {
21 using std::vector;
22 
23 void CrystalGen::extractPositions(std::vector<Point3D> &data)
24 {
25  data.resize(localData.size());
26 #pragma omp parallel for
27  for(size_t ui=0;ui<data.size();ui++)
28  data[ui]=localData[ui].getPosRef();
29 
30  localData.clear();
31 }
32 
34 {
35  vector<IonHit> h;
36  h.swap(localData);
37 
38 
39  localData.resize(h.size()*8);
40 
41  size_t offset=0;
42  for(int ui=0;ui<8;ui++)
43  {
44  //Generate a point that is one of any of the (+-1,+-1,+-1)
45  // permutations
46  Point3D p;
47  p=Point3D(2*(ui&1)-1, 2*((ui&2)>>1) -1, 2*((ui&4)>>2) -1);
48 
49  //Multiply this point by the data
50  for(unsigned int uj=0;uj<h.size();uj++)
51  {
52 
53  localData[offset].setPos(p*h[uj].getPosRef());
54  localData[offset].setMassToCharge(h[uj].getMassToCharge());
55  offset++;
56  }
57  }
58 
59 
60 }
61 
62 SimpleCubicGen::SimpleCubicGen(float latticeSpacing, float massToC, const Point3D &p)
63 {
64  spacing=latticeSpacing;
65  massToCharge=massToC;
66  farPoint=p;
67 }
68 
70 {
71  //Firstly we have to load the unit cell, which in a cubic
72  //lattice and thus contains one atom
73  IonHit atom(Point3D(0,0,0),0);
74  //atomic spacing in nanometres
75 
76  if(std::isnan(massToCharge))
77  return CRYSTAL_BAD_UNIT_CELL;
78 
79  //check for lack of atomic spacing
80  if(spacing <= 0.0f)
81  return CRYSTAL_BAD_UNIT_CELL;
82 
83  //check for a good bounding value
84  for(unsigned int ui=0; ui<3; ui++)
85  {
86  if(farPoint.getValue(ui) <=0.0f)
87  return CRYSTAL_BAD_UNIT_CELL;
88  }
89 
90  //OK, so we have checked we have a good unit cell, now lets populate!
91  //estimate how many entries we will need in localData
92  localData.clear();
93 
94  //Use volume estimation to estimate number of points to be stored
95  localData.reserve((int)(farPoint.getValue(0)*farPoint.getValue(1)*
96  farPoint.getValue(2)/(spacing*
97  spacing*spacing)));
98 
99 
100  //set up the positions of the unit cell
101  //These have been kept as function calls because to
102  //ensure internal consistency
103 
104  //Create the crystal lattice
105  // FIXME: With sufficiently nasty input, this could inf. loop
106  for(float fX=0; fX<farPoint.getValue(0); fX+=spacing)
107  {
108  for(float fY=0; fY<farPoint.getValue(1); fY+=spacing)
109  {
110  for(float fZ=0; fZ<farPoint.getValue(2);fZ+=spacing)
111  {
112  atom.setPos(Point3D(fX,fY,fZ));
113  localData.push_back(atom);
114  }
115  }
116  }
117  return 0;
118 }
119 
120 FaceCentredCubicGen::FaceCentredCubicGen(float latticeSpacing, float massToCCorner,
121  const float *massToCFace, const Point3D &p)
122 {
123  spacing=latticeSpacing;
124  massToChargeCorner=massToCCorner;
125  for(unsigned int ui=0;ui<3;ui++)
126  massToChargeFace[ui]=massToCFace[ui];
127  farPoint=p;
128 }
129 
131 {
132 
133  //the option vector must contain the unit cell
134  //indices are in reciprocal values (integer)
135  //if reciprocal is infinite, it becomes 0
136 
137  //The unit cell has 14 vertices of which 4 are unique
138  // the corner atoms are all the same,
139  // the faces however have up/down, east/west,north/south
140  // as unique groups
141  IonHit atomList[4];
142  //Set the mass to charges to a bad value
143  atomList[0].setMassToCharge(massToChargeCorner);
144  for(unsigned int ui=0;ui<3;ui++)
145  atomList[1+ui].setMassToCharge(massToChargeFace[ui]);
146 
147  //Check atomic spacing is valid
148  if(spacing<=0.0f)
149  return CRYSTAL_BAD_UNIT_CELL;
150 
151  //check for a good bounding value
152  for(unsigned int ui=0; ui<3; ui++)
153  {
154  if(farPoint.getValue(ui) <=0.0f)
155  return CRYSTAL_BAD_UNIT_CELL;
156  }
157 
158  //OK, so now we have a good unit cell lets do the replication thing!
159 
160  //This is an approximation and ignores some boundary issues
161  //but it is good enough for a call to "reserve".
162  localData.reserve(localData.size() + (unsigned int)(farPoint.getValue(0)/spacing)*
163  (unsigned int)(farPoint.getValue(1)/spacing)*
164  (unsigned int)(farPoint.getValue(2)) );
165 
166  //Top view
167  //===============
168  //* D *
169  //
170  //O X O
171  //
172  //* D *
173 
174  //Firstly lay down the simple cubic lattice (*s)
175  float xMax,yMax,zMax;
176  Point3D pt;
177  xMax = farPoint.getValue(0);
178  yMax = farPoint.getValue(1);
179  zMax = farPoint.getValue(2);
180 
181  IonHit curAtom = atomList[0];
182  for(float fX=0.0f; fX<xMax; fX+=spacing)
183  {
184  for(float fY=0.0f; fY<yMax; fY+=spacing)
185  {
186  for(float fZ=0.0f; fZ<zMax; fZ+=spacing)
187  {
188  curAtom.setPos(fX,fY,fZ);
189  localData.push_back(curAtom);
190  }
191  }
192  }
193 
194  //Lay down the "X" sites
195  curAtom = atomList[1];
196  for(float fX=spacing/2.0f; fX<xMax; fX+=spacing)
197  {
198  for(float fY=spacing/2.0f; fY<yMax; fY+=spacing)
199  {
200  for(float fZ=0.0f; fZ<zMax; fZ+=spacing)
201  {
202  curAtom.setPos(fX,fY,fZ);
203  localData.push_back(curAtom);
204  }
205  }
206  }
207 
208  //Lay down the D sites
209  curAtom = atomList[2];
210  for(float fX=spacing/2.0f; fX<xMax; fX+=spacing)
211  {
212  for(float fY=0.0; fY<yMax; fY+=spacing)
213  {
214  for(float fZ=spacing/2.0f; fZ<zMax; fZ+=spacing)
215  {
216  curAtom.setPos(fX,fY,fZ);
217  localData.push_back(curAtom);
218  }
219  }
220  }
221 
222  //Lay down the "O" sites
223  curAtom = atomList[3];
224  for(float fX=0.0; fX<xMax; fX+=spacing)
225  {
226  for(float fY=spacing/2.0f; fY<yMax; fY+=spacing)
227  {
228  for(float fZ=spacing/2.0f; fZ<zMax; fZ+=spacing)
229  {
230  curAtom.setPos(fX,fY,fZ);
231  localData.push_back(curAtom);
232  }
233  }
234  }
235 
236  return 0;
237 }
238 
239 BodyCentredCubicGen::BodyCentredCubicGen(float latticeSpacing, float massToCCorner,
240  const float massToCCentre, const Point3D &p)
241 {
242  spacing=latticeSpacing;
243  massToChargeCorner=massToCCorner;
244  massToChargeCentre=massToCCentre;
245  farPoint=p;
246 }
247 
249 {
250 
251  //the option vector must contain the unit cell
252  //indices are in reciprocal values (integer)
253  //if reciprocal is infinite, it becomes 0
254 
255  //The unit cell has 14 vertices of which 4 are unique
256  // the corner atoms are all the same,
257  // the faces however have up/down, east/west,north/south
258  // as unique groups
259  IonHit atomList[2];
260  //Set the mass to charges to a bad value
261  atomList[0].setMassToCharge(massToChargeCorner);
262  atomList[1].setMassToCharge(massToChargeCentre);
263 
264  //Check atomic spacing is valid
265  if(spacing<=0.0f)
266  return CRYSTAL_BAD_UNIT_CELL;
267 
268  //check for a good bounding value
269  for(unsigned int ui=0; ui<3; ui++)
270  {
271  if(farPoint.getValue(ui) <=0.0f)
272  return CRYSTAL_BAD_UNIT_CELL;
273  }
274 
275  //OK, so now we have a good unit cell lets do the replication thing!
276 
277  //This is an approximation and ignores some boundary issues
278  //but it is good enough for a call to "reserve".
279  localData.reserve(localData.size() + (unsigned int)(farPoint.getValue(0)/spacing)*
280  (unsigned int)(farPoint.getValue(1)/spacing)*
281  (unsigned int)(farPoint.getValue(2)) );
282 
283 
284  //Firstly lay down the simple cubic lattice
285  // then fill in the centre
286  float xMax,yMax,zMax;
287  Point3D pt;
288  xMax = farPoint.getValue(0);
289  yMax = farPoint.getValue(1);
290  zMax = farPoint.getValue(2);
291 
292  IonHit curAtom = atomList[0];
293  IonHit curCentreAtom = atomList[1];
294  for(float fX=0.0f; fX<xMax; fX+=spacing)
295  {
296  for(float fY=0.0f; fY<yMax; fY+=spacing)
297  {
298  for(float fZ=0.0f; fZ<zMax; fZ+=spacing)
299  {
300  curAtom.setPos(fX,fY,fZ);
301  localData.push_back(curAtom);
302 
303  //FIXME: This is quite inefficient.
304  Point3D pCentre;
305  pCentre=Point3D(fX+spacing/2.0f,
306  fY+spacing/2.0f,fZ+spacing/2.0f);
307  if(pCentre[0]<farPoint[0] && pCentre[1] < farPoint[1]
308  && pCentre[2] < farPoint[2])
309  {
310  curCentreAtom.setPos(pCentre);
311  localData.push_back(curCentreAtom);
312  }
313 
314  }
315  }
316  }
317 
318 
319  return 0;
320 }
321 
322 #ifdef DEBUG
324 #include "helper/helpFuncs.h"
325 
326 bool runGenerateTests()
327 {
328  SimpleCubicGen scg(1,1,Point3D(10,10,10));
329  scg.generateLattice();
330 
331  vector<Point3D> pts;
332  scg.extractPositions(pts);
333  TEST(pts.size() > 800,"ion count");
334  BoundCube bc;
335  bc.setBounds(pts);
336 
337  for(unsigned int ui=0;ui<3;ui++)
338  {
339  TEST(TOL_EQ_V(bc.getSize(0),10,1.1),"cube size");
340  }
341  return true;
342 }
343 #endif
344 
345 
346 }
347 
unsigned int generateLattice()
Definition: generate.cpp:130
virtual void mirrorOut()
Definition: generate.cpp:33
unsigned int generateLattice()
Definition: generate.cpp:69
#define TEST(f, g)
Definition: aptAssert.h:49
void setPos(const Point3D &pos)
Definition: ionhit.cpp:76
A 3D point data class storage.
Definition: point3D.h:39
FaceCentredCubicGen(float latticeSpacing, float mToCCorner, const float *mToCFace, const Point3D &p)
Definition: generate.cpp:120
std::vector< IonHit > localData
Definition: generate.h:34
Helper class to define a bounding cube.
Definition: boundcube.h:29
void setMassToCharge(float newMassToCharge)
Definition: ionhit.cpp:60
This is a data holding class for POS file ions, from.
Definition: ionHit.h:36
BodyCentredCubicGen(float latticeSpacing, float mToCCentre, const float mToCCorner, const Point3D &p)
Definition: generate.cpp:239
float getValue(unsigned int ui) const
Get value of ith dimension (0, 1, 2)
Definition: point3D.h:98
SimpleCubicGen(float latticeSpacing, float massToC, const Point3D &p)
Definition: generate.cpp:62
unsigned int generateLattice()
Definition: generate.cpp:248
virtual void extractPositions(std::vector< Point3D > &data)
Definition: generate.cpp:23
void setBounds(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax)
Set the bounds by passing in minima and maxima of each dimension.
Definition: boundcube.cpp:49