oILAB
Loading...
Searching...
No Matches
Gb.cpp
Go to the documentation of this file.
1//
2// Created by Nikhil Chandra Admal on 11/5/22.
3//
4#ifndef OILAB_GB_CPP
5#define OILAB_GB_CPP
6
7#include "Gb.h"
8
9namespace gbLAB
10{
11 template<int dim>
13 try :
14 /* init */ bc(bc)
15 /* init */,nA(&n.lattice == &(bc.A) ? n : bc.getReciprocalLatticeDirectionInA(-1*n.reciprocalLatticeVector()))
16 /* init */,nB(&n.lattice == &(bc.B) ? n : bc.getReciprocalLatticeDirectionInB(-1*n.reciprocalLatticeVector()))
17 /* init */,basisT(getBasisT(bc,n))
18 /* init */,T(Lattice<dim>(bc.dscl.latticeBasis*getBasisT(bc,n).template cast<double>()))
19 {
20 if (&n.lattice != &(bc.A) && &n.lattice != &(bc.B))
21 throw std::runtime_error("The normal does not belong to the reciprocal lattices of A and B \n");
22 }
23 catch(std::runtime_error& e)
24 {
25 std::cout << e.what() << std::endl;
26 throw(std::runtime_error("GB construction failed. "));
27 }
28
29 template<int dim>
31 {
32 ReciprocalLatticeDirection<dim> dir= bc.getReciprocalLatticeDirectionInC(nA.reciprocalLatticeVector());
33 double cslPlaneSpacing= dir.planeSpacing();
34 double step= bc.shiftTensorA(d).cartesian().dot(nA.cartesian().normalized());
35 return std::remainder(step,cslPlaneSpacing);
36 }
37
38 template<int dim>
40 {
41 ReciprocalLatticeDirection<dim> dir= bc.getReciprocalLatticeDirectionInC(nA.reciprocalLatticeVector());
42 double cslPlaneSpacing= dir.planeSpacing();
43 double step= (bc.shiftTensorA(d)-bc.shiftTensorB(d)).cartesian().dot(nA.cartesian().normalized())/2.0;
44 return std::remainder(step,cslPlaneSpacing);
45 }
46
47 template<int dim>
49 {
50 ReciprocalLatticeDirection<dim> dir= bc.getReciprocalLatticeDirectionInC(nA.reciprocalLatticeVector());
51 double cslPlaneSpacing= dir.planeSpacing();
52 double step= bc.shiftTensorB(d).cartesian().dot(nB.cartesian().normalized());
53 return std::remainder(step,cslPlaneSpacing);
54 }
55
56 template<int dim> template<int dm>
57 typename std::enable_if<dm==2 || dm==3,std::vector<LatticeVector<dim>>>::type
58 Gb<dim>::box(std::vector<LatticeVector<dim>>& boxVectors,
59 const double& orthogonality,
60 const int& dsclFactor,
61 std::string filename,
62 bool orient) const
63 {
64 for (auto iter= std::next(boxVectors.begin()); iter < boxVectors.end(); iter++)
65 assert((*iter).dot(bc.getReciprocalLatticeDirectionInC(nA.reciprocalLatticeVector())) == 0 &&
66 "Box vectors not parallel to the grain boundary.");
67
68 auto config= bc.box(boxVectors,orthogonality,dsclFactor);
69 std::vector<LatticeVector<dim>> configuration;
70 for (const LatticeVector<dim>& latticeVector : config)
71 {
72 if (&(latticeVector.lattice) == &bc.A && latticeVector.dot(nA)<=0)
73 configuration.push_back(latticeVector);
74 if (&(latticeVector.lattice) == &bc.B && latticeVector.dot(nB)<=0)
75 configuration.push_back(latticeVector);
76 if (&(latticeVector.lattice) == &bc.csl || &(latticeVector.lattice) == &bc.dscl)
77 configuration.push_back(latticeVector);
78 }
79
80 // form the rotation matrix used to orient the system
81 MatrixDimD rotation= Eigen::Matrix<double,dim,dim>::Identity();;
82 Eigen::Matrix<double,dim,dim-1> orthogonalVectors;
83 if (orient) {
84 if (dim==3) {
85 orthogonalVectors.col(0) = boxVectors[1].cartesian().normalized();
86 orthogonalVectors.col(1) = boxVectors[2].cartesian().normalized();
87 }
88 else if (dim==2)
89 orthogonalVectors.col(0)= boxVectors[1].cartesian().normalized();
90
91 rotation=Rotation<dim>(orthogonalVectors);
92 }
93 //assert((rotation*rotation.transpose()).template isApprox(Eigen::Matrix<double,dim,dim>::Identity())
94 assert((rotation*rotation.transpose()).isApprox(Eigen::Matrix<double,dim,dim>::Identity())
95 && "Cannot orient the grain boundary. The GB plane box vectors are not orthogonal.");
96
97 if(!filename.empty()) {
98 std::ofstream file;
99 file.open(filename);
100 if (!file) std::cerr << "Unable to open file";
101 file << configuration.size() << std::endl;
102 file << "Lattice=\"";
103
104 LatticeVector<dim> origin(-1*boxVectors[0]);
105 if (dim == 2) {
106 file << (rotation * 2 * boxVectors[0].cartesian()).transpose() << " 0 ";
107 file << (rotation * boxVectors[1].cartesian()).transpose() << " 0 ";
108 file << " 0 0 1 ";
109 file << "\" Properties=atom_types:I:1:pos:R:3:radius:R:1 PBC=\"F T T\" origin=\"";
110 file << (rotation * origin.cartesian()).transpose() << " 0.0\"" << std::endl;
111 for (const auto &vector: configuration)
112 if (&(vector.lattice) == &bc.A)
113 file << 1 << " " << (rotation * vector.cartesian()).transpose() << " " << 0.0 << " "
114 << 0.05 << std::endl;
115 else if (&(vector.lattice) == &bc.B)
116 file << 2 << " " << (rotation * vector.cartesian()).transpose() << " " << 0.0 << " "
117 << 0.05 << std::endl;
118 else if (&(vector.lattice) == &bc.csl)
119 file << 3 << " " << (rotation * vector.cartesian()).transpose() << " " << 0.0 << " " << 0.2
120 << std::endl;
121 else
122 file << 4 << " " << (rotation * vector.cartesian()).transpose() << " " << 0.0 << " "
123 << 0.01 << std::endl;
124 } else if (dim == 3) {
125 file << (rotation * 2 * boxVectors[0].cartesian()).transpose() << " ";
126 file << (rotation * boxVectors[1].cartesian()).transpose() << " ";
127 file << (rotation * boxVectors[2].cartesian()).transpose() << " ";
128 file << "\" Properties=atom_types:I:1:pos:R:3:radius:R:1 PBC=\"F T T\" origin=\"";
129 file << (rotation * origin.cartesian()).transpose() << "\"" << std::endl;
130
131 for (const auto &vector: configuration)
132 if (&(vector.lattice) == &bc.A)
133 file << 1 << " " << (rotation * vector.cartesian()).transpose() << " " << 0.05
134 << std::endl;
135 else if (&(vector.lattice) == &bc.B)
136 file << 2 << " " << (rotation * vector.cartesian()).transpose() << " " << 0.05
137 << std::endl;
138 else if (&(vector.lattice) == &bc.csl)
139 file << 3 << " " << (rotation * vector.cartesian()).transpose() << " " << 0.2 << std::endl;
140 else
141 file << 4 << " " << (rotation * vector.cartesian()).transpose() << " " << 0.01
142 << std::endl;
143 }
144 file.close();
145 }
146 return configuration;
147 }
148
149 template<int dim> template<int dm>
150 typename std::enable_if<dm==2,LatticeVector<dim>>::type
152 {
153 LatticeVector<dm> axisAxnA(nA.reciprocalLatticeVector().cross().latticeVector());
154 return (LatticeVector<dm>(bc.getLatticeDirectionInC(axisAxnA).latticeVector()));
155 }
156
157 template<int dim> template<int dm>
158 typename std::enable_if<dm==3,LatticeVector<dim>>::type
160 {
161 assert(abs(nA.cartesian().dot(axis.cartesian())) < FLT_EPSILON);
162 ReciprocalLatticeDirection<dm> axisA(bc.A.reciprocalLatticeVector(axis.cartesian()));
163 LatticeVector<dm> axisAxnA(axisA.reciprocalLatticeVector().cross(nA.reciprocalLatticeVector()).latticeVector());
164 return (LatticeVector<dm>(bc.getLatticeDirectionInC(axisAxnA).latticeVector()));
165 }
166
167
168 template<int dim>
170 {
171 MatrixDimI output;
172 MatrixDimI Q = 2*bc.LambdaA-Eigen::Matrix<IntScalarType,dim,dim>::Identity();
173 auto nC= bc.getReciprocalLatticeDirectionInC(this->nB.reciprocalLatticeVector());
174
177
178 IntScalarType detMN= (bc.M*bc.N).template cast<double>().determinant();
179 Eigen::DiagonalMatrix<IntScalarType,dim> nCDiagonal(nC.reciprocalLatticeVector());
180 RationalMatrix<dim> temp(adjM*adjN*Q*nCDiagonal, Eigen::Matrix<IntScalarType,dim,dim>::Constant(2*detMN));
181
182 IntScalarType alpha= IntegerMath<IntScalarType>::gcd(temp.integerMatrix.diagonal().eval());
183 IntScalarType beta= temp.mu;
185
186 assert(IntegerMath<IntScalarType>::gcd(alpha,beta) == 1);
187
188 //auto basis= bc.dscl.planeParallelLatticeBasis(m,true);
189 auto basis= bc.dscl.planeParallelLatticeBasis(m,false);
190 for(int i=0; i<dim; ++i) {
191 output.col(i) = basis[i].latticeVector();
192 if (i==0) output.col(i)= beta*output.col(i);
193 }
194 return output;
195 }
196
197 template<int dim>
199 {
201 IntScalarType det= basisT.template cast<double>().determinant();
202 // basisTA
203 // T --------> dscl
204 if (&(v.lattice) == &(bc.csl) && IntegerMath<IntScalarType>::gcd(v)%2 == 0)
205 {
206 VectorDimI integerCoordinates= adj * bc.getLatticeVectorInD(v);
207 assert(IntegerMath<IntScalarType>::gcd(integerCoordinates) % det == 0);
208 integerCoordinates= integerCoordinates/det;
209
210 auto temp= LatticeVector<dim>(integerCoordinates,T);
211 if (temp.cartesian().dot(v.cartesian()) < 0) temp= -1*temp;
212 return temp;
213 }
214 else
215 throw(std::runtime_error("The input lattice vector should belong to twice the CSL lattice"));
216
217 }
218
219 template<int dim>
221 {
222 // basisTA
223 // T --------> dscl
224 if (&(v.lattice) == &(bc.dscl))
225 return ReciprocalLatticeVector<dim>((basisT.transpose()*v).eval(),T);
226 else
227 throw(std::runtime_error("The input reciprocal lattice vector should belong to the reciprocal lattice of the DSCL"));
228
229 }
230
231 template<int dim>
236
237 template class Gb<2>;
239 template std::vector<LatticeVector<2>> Gb<2>::box<2>(std::vector<LatticeVector<2>>& boxVectors,
240 const double& orthogonality,
241 const int& dsclFactor,
242 std::string filename,
243 bool orient) const;
244
245 template class Gb<3>;
247 template std::vector<LatticeVector<3>> Gb<3>::box<3>(std::vector<LatticeVector<3>>& boxVectors,
248 const double& orthogonality,
249 const int& dsclFactor,
250 std::string filename,
251 bool orient) const;
252
253 template class Gb<4>;
254 template class Gb<5>;
255}
256
257
258#endif //OILAB_GB_CPP
const Lattice< dim > dscl
DCSL lattice .
Definition BiCrystal.h:90
ReciprocalLatticeDirection< dim > getReciprocalLatticeDirectionInC(const ReciprocalLatticeVector< dim > &v) const
const MatrixDimI M
Integer matrix that connects the bases and of lattices and the CSL , respectively: .
Definition BiCrystal.h:62
const MatrixDimI N
Integer matrix that connects the bases and of lattices and the CSL , respectively: .
Definition BiCrystal.h:67
const MatrixDimI LambdaA
Shift tensor describes the shift in the CSL when lattice is shifted by a DSCL vector.
Definition BiCrystal.h:103
Definition Gb.h:16
Gb(const BiCrystal< dim > &bc, const ReciprocalLatticeDirection< dim > &n)
Constructs a grain boundary of a given orientation in a bicrystal.
Definition Gb.cpp:12
typename LatticeCore< dim >::MatrixDimI MatrixDimI
Definition Gb.h:20
ReciprocalLatticeDirection< dim > getReciprocalLatticeDirectionInT(const ReciprocalLatticeVector< dim > &v) const
Definition Gb.cpp:232
typename LatticeCore< dim >::MatrixDimD MatrixDimD
Definition Gb.h:19
typename LatticeCore< dim >::IntScalarType IntScalarType
Definition Gb.h:21
typename LatticeCore< dim >::VectorDimI VectorDimI
Definition Gb.h:17
double stepHeightA(const LatticeVector< dim > &d) const
Computes the step height of a disconnection formed by displacing lattice by a Burgers vector .
Definition Gb.cpp:30
const BiCrystal< dim > & bc
Definition Gb.h:29
std::enable_if< dm==2||dm==3, std::vector< LatticeVector< dim > > >::type box(std::vector< LatticeVector< dim > > &boxVectors, const double &orthogonality, const int &dsclFactor, std::string filename="", bool orient=false) const
Definition Gb.cpp:58
MatrixDimI getBasisT(const BiCrystal< dim > &bc, const ReciprocalLatticeDirection< dim > &n)
Definition Gb.cpp:169
std::enable_if< dm==2, LatticeVector< dim > >::type getPeriodVector(const ReciprocalLatticeVector< dim > &axis) const
Definition Gb.cpp:151
double stepHeight(const LatticeVector< dim > &d) const
Computes the step height of a disconnection formed by displacing lattice by and by
Definition Gb.cpp:39
double stepHeightB(const LatticeVector< dim > &d) const
Computes the step height of a disconnection formed by displacing lattice by a Burgers vector .
Definition Gb.cpp:48
ReciprocalLatticeVector< dim > getReciprocalLatticeVectorInT(const ReciprocalLatticeVector< dim > &v) const
Definition Gb.cpp:220
LatticeVector< dim > getLatticeVectorInT(const LatticeVector< dim > &v) const
Definition Gb.cpp:198
Lattice class.
Definition Lattice.h:34
LatticeVector class.
VectorDimD cartesian() const
const Lattice< dim > & lattice
static Eigen::Matrix< IntScalarType, dim, dim > adjoint(const Eigen::Matrix< IntScalarType, dim, dim > &input)
const IntScalarType & mu
const MatrixDimI & integerMatrix
static IntScalarType gcd(const IntScalarType &a, const IntScalarType &b)
Definition IntegerMath.h:33
double planeSpacing() const
Returns the spacing between two consecutive lattice planes.
const ReciprocalLatticeVector< dim > & reciprocalLatticeVector() const
Returns a constant reference to the base class (ReciprocalLatticeVector)