10 #include <gsl/gsl_linalg.h> 18 for (
size_t i = 0; i < m->size1; i++)
20 for (
size_t j = 0; j < m->size2; j++)
22 cerr << gsl_matrix_get(m,i,j) <<
" ";
34 int main(
int argc,
char *argv[])
36 if(! (argc==6 || argc ==7 || argc == 8))
38 cerr <<
"Simulates the projection coordinates in an APT pole figure (simple cubic lattice), using the method of Perry & Brandon [1]. (Make spherical shell and project)" << endl;
40 cerr <<
"Usage: LATTICENAME SCALE_TO_LATTICE THICKNESS_TO_LATTICE FOCUS FLIGHT_PATH [Forwards_vector] [right_vector|rotation_angle]" << endl;
41 cerr <<
"LATTICENAME : Any of \"Simple\" (simple cubic), FCC or BCC." << endl;
42 cerr <<
"SCALE_TO_LATTICE : This ratio is the density of atoms to project, i.e the number of atoms in the simulation in one direction." << endl;
43 cerr <<
"THICKNESS_TO_LATTICE: Number of lattice slices to take from shell. Moore suggests 0.1" << endl;
44 cerr <<
"FOCUS : The centre projection point for the modified stereographic projection. Sometimes called \"Image compression factor\". Must be >=1" << endl;
45 cerr <<
"FLIGHT_PATH : The units here are arbitrary, and just scale the projection" << endl;
47 cerr <<
"These values are dimensionless, as the projection problem can be expressed as a dimensionlessly (i.e. independently of lattice parameter)" << endl;
52 cerr <<
"Forwards vector : The vector to place at the centre of the pole figure, eg 0,1,0" << endl;
53 cerr <<
"Right vector : The vector to place as the right-most point of the pole figure, eg 1,0,1. If provided, this must be orthogonal to the forwards vector" << endl;
54 cerr <<
" Instead of the right vector, you can provide a rotation angle (degrees). This will rotate the crystal around 0,0,1 (world) after the initial transformation" << endl;
59 cerr <<
"[1] A. J. Perry & D. G. Brandon, The bond structure of computer-simulated field-ion images, Philosophical Magazine" << endl;
62 cerr <<
"Example:" << argv[0] <<
" 10 4 1" << endl;
65 cerr <<
"You can rotate the pole centre by specifying the central atom vector, and the the right hand vector" << endl;
66 cerr <<
"Example:" << argv[0] <<
" 10 4 (1,1,1) (0,0,1)" << endl;
70 cerr <<
"Output:" << endl;
71 cerr <<
"The output is a 2-column vector with the detector positions. These are in the units given by the FLIGHT_PATH" << endl;
72 cerr <<
"To work out if these would land on any given detector, you must perform this computation externally to this program. All possible visible points from the projection will be shown" << endl;
78 float scaleToLattice,thicknessToLattice,focus,flightPath;
92 bool specifiedForwards=
false;
94 specifiedForwards=
true;
95 bool specifiedRight=
false;
102 if(scaleToLattice <= 1e-5)
104 cerr <<
"Scale/Lattice ratio too small!" << endl;
108 if(thicknessToLattice <=1e-5)
110 cerr <<
"Thickness/lattice ratio too small" << endl;
117 cerr <<
"Projection focus must be greater than -1" << endl;
123 cerr <<
"Flight path must be positive" << endl;
130 float postRotateAngle=0.0f;
135 if(specifiedForwards || specifiedRight)
137 if(!forwardsVec.
parse(argv[6]))
139 cerr <<
"Error parsing forwards vector (centre of figure)" << endl;
146 if(!rightVec.
parse(argv[7]))
150 cerr <<
"Error parsing right vector/rotation angle " << endl;
156 postRotateAngle*=
M_PI/180.0f;
158 cerr <<
"Right vector is :" << rightVec << endl;
166 cerr <<
"Right vector is :" << rightVec << endl;
171 if(fabs(forwardsVec.
sqrMag() -1.0f) > 1e-3 ||
172 fabs(rightVec.
sqrMag() -1.0f) > 1e-3)
174 cerr <<
"Input vectors could not be normalised." << endl;
178 if(fabs(forwardsVec.
dotProd(rightVec)) > 1e-3)
180 cerr <<
"Requested pole figure vectors are not orthogonal. " << endl;
198 LATTICE_SIMPLE_CUBIC,
203 map<string,unsigned int> latticeNameMap;
204 latticeNameMap[
"simple"] = LATTICE_SIMPLE_CUBIC;
209 string latticeName=argv[1];
212 unsigned int latticeType;
213 auto it =latticeNameMap.find(latticeName);
214 if(it== latticeNameMap.end())
216 cerr <<
"Unsupported or unknown lattice:" << latticeName << endl;
220 latticeType=it->second;
225 Point3D p(scaleToLattice,scaleToLattice,scaleToLattice);
231 case LATTICE_SIMPLE_CUBIC:
236 const float massToCharge[3]={1,1,1};
247 cerr <<
"Unknown lattice. Aborting" << endl;
258 cerr <<
"Full lattice contains :" << h.size() <<
"pts" << endl;
268 gsl_matrix *rMat = gsl_matrix_alloc(3,3);
274 gsl_matrix_transpose(rMat);
276 for(
unsigned int ui=0;ui<h.size();ui++)
277 h[ui].transform3x3(rMat);
280 if(postRotateAngle!=0.0f)
282 float sR = sin(postRotateAngle);
283 float cR = cos(postRotateAngle);
284 #pragma omp parallel for 285 for(
unsigned int ui=0;ui<h.size();ui++)
290 pt[0] = h[ui][0]*cR - h[ui][1]*sR;
291 pt[1] = h[ui][0]*sR + h[ui][1]*cR;
296 gsl_matrix *m=gsl_matrix_alloc(3,3);
297 gsl_matrix_set_identity(m);
298 gsl_matrix_set(m,0,0,cR);
299 gsl_matrix_set(m,0,1,-sR);
300 gsl_matrix_set(m,1,0,sR);
301 gsl_matrix_set(m,0,1,cR);
304 gsl_matrix_transpose(m);
307 gsl_matrix *tmp=gsl_matrix_alloc(3,3);
311 gsl_matrix_free(tmp);
316 gsl_matrix_transpose(rMat);
319 cerr <<
"Reverse transformation (World -> crystal)" << endl;
320 cerr <<
"-----------------" << endl;
322 cerr <<
"-----------------" << endl;
324 gsl_matrix_free(rMat);
331 vector<Point3D> quadPts;
332 for(
unsigned int ui=0;ui<h.size();ui++)
335 quadPts.push_back(h[ui]);
347 float deltaMin=(scaleToLattice-thicknessToLattice)*(scaleToLattice-thicknessToLattice);
348 float deltaMax=(scaleToLattice)*(scaleToLattice);
349 for(
size_t ui=0;ui<h.size();ui++)
352 rSqr = ( h[ui].sqrMag());
354 if( rSqr > deltaMin && rSqr < deltaMax)
355 pts.push_back(h[ui]);
358 cerr <<
"Sliced out :" << pts.size() <<
" pts" << endl;
362 cerr <<
"No points outputted. Consider increasing your lattice density (scale/lattice) or slice thickness" << endl;
370 vector<pair<float,float> > pXY;
373 for(
size_t ui=0;ui<pts.size() ;ui++)
377 pts[ui].getISOSpherical(r,eta,phi);
384 if( eta < maxFOV && mSp.
toPlanar(theta,phi,pX,pY))
386 pXY.push_back(make_pair(pX,pY));
393 float flightFactor=flightPath/(focus+1);
396 ofstream fProj(
"projection.txt");
399 cerr <<
"Failed to open output file, aborting" << endl;
405 fProj <<
"# Arguments used: ";
406 for(
unsigned int ui=1;ui<argc;ui++)
407 fProj << argv[ui] <<
" ";
411 for(
size_t ui=0;ui<pXY.size();ui++)
413 fProj << pXY[ui].first*flightFactor <<
" , " << pXY[ui].second*flightFactor << endl;
416 cerr <<
"Wrote detector coordinates to projection.txt" << endl;
void computeRotationMatrix(const Point3D &ur1, const Point3D &ur2, const Point3D &r1, const Point3D &r2, gsl_matrix *m)
Point3D crossProd(const Point3D &pt) const
Calculate the cross product of this and another point.
void gsl_matrix_mult(const gsl_matrix *A, const gsl_matrix *B, gsl_matrix *&res, bool alloc=false)
virtual unsigned int generateLattice()=0
float sqrMag() const
Returns magnitude^2, taking this as a position vector.
unsigned int savePosFile(const std::vector< Point3D > &points, float mass, const char *name, bool append=false)
Save a vector of Point3Ds into a pos file, using a fixed mass, return nonzero on error.
A 3D point data class storage.
bool parse(const std::string &s)
Set from string representation.
virtual bool toPlanar(float theta, float phi, float &fx, float &fy) const
Convert from stereographic (NOT SPHERICAL) coordinates to plane.
float etaToTheta(float eta) const
Convert the spherical angle to an azimuthal angle. See docs/figures for examples. ...
void normalise()
Make point unit magnitude, maintaining direction.
std::string lowercase(std::string s)
Return a lowercase version for a given string.
float getMaxFOV() const
Obtain angle spherical angle, eta, (i.e. angle from point of sphere, sphere centre and x axis) of the...
bool stream_cast(T1 &result, const T2 &obj)
Template function to cast and object to another by the stringstream.
float dotProd(const Point3D &pt) const
Calculate the dot product of this and another point.
virtual void extractPositions(std::vector< Point3D > &data)