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.shiftTensorB(d).cartesian().dot(nB.cartesian().normalized());
44 return std::remainder(step,cslPlaneSpacing);
45 }
46
47 template<int dim> template<int dm>
48 typename std::enable_if<dm==2 || dm==3,std::vector<LatticeVector<dim>>>::type
49 Gb<dim>::box(std::vector<LatticeVector<dim>>& boxVectors,
50 const double& orthogonality,
51 const int& dsclFactor,
52 std::string filename,
53 bool orient) const
54 {
55 for (auto iter= std::next(boxVectors.begin()); iter < boxVectors.end(); iter++)
56 assert((*iter).dot(bc.getReciprocalLatticeDirectionInC(nA.reciprocalLatticeVector())) == 0 &&
57 "Box vectors not parallel to the grain boundary.");
58
59 auto config= bc.box(boxVectors,orthogonality,dsclFactor);
60 std::vector<LatticeVector<dim>> configuration;
61 for (const LatticeVector<dim>& latticeVector : config)
62 {
63 if (&(latticeVector.lattice) == &bc.A && latticeVector.dot(nA)<=0)
64 configuration.push_back(latticeVector);
65 if (&(latticeVector.lattice) == &bc.B && latticeVector.dot(nB)<=0)
66 configuration.push_back(latticeVector);
67 if (&(latticeVector.lattice) == &bc.csl || &(latticeVector.lattice) == &bc.dscl)
68 configuration.push_back(latticeVector);
69 }
70
71 // form the rotation matrix used to orient the system
72 MatrixDimD rotation= Eigen::Matrix<double,dim,dim>::Identity();;
73 Eigen::Matrix<double,dim,dim-1> orthogonalVectors;
74 if (orient) {
75 if (dim==3) {
76 orthogonalVectors.col(0) = boxVectors[1].cartesian().normalized();
77 orthogonalVectors.col(1) = boxVectors[2].cartesian().normalized();
78 }
79 else if (dim==2)
80 orthogonalVectors.col(0)= boxVectors[1].cartesian().normalized();
81
82 rotation=Rotation<dim>(orthogonalVectors);
83 }
84 //assert((rotation*rotation.transpose()).template isApprox(Eigen::Matrix<double,dim,dim>::Identity())
85 assert((rotation*rotation.transpose()).isApprox(Eigen::Matrix<double,dim,dim>::Identity())
86 && "Cannot orient the grain boundary. The GB plane box vectors are not orthogonal.");
87
88 if(!filename.empty()) {
89 std::ofstream file;
90 file.open(filename);
91 if (!file) std::cerr << "Unable to open file";
92 file << configuration.size() << std::endl;
93 file << "Lattice=\"";
94
95 LatticeVector<dim> origin(-1*boxVectors[0]);
96 if (dim == 2) {
97 file << (rotation * 2 * boxVectors[0].cartesian()).transpose() << " 0 ";
98 file << (rotation * boxVectors[1].cartesian()).transpose() << " 0 ";
99 file << " 0 0 1 ";
100 file << "\" Properties=atom_types:I:1:pos:R:3:radius:R:1 PBC=\"F T T\" origin=\"";
101 file << (rotation * origin.cartesian()).transpose() << " 0.0\"" << std::endl;
102 for (const auto &vector: configuration)
103 if (&(vector.lattice) == &bc.A)
104 file << 1 << " " << (rotation * vector.cartesian()).transpose() << " " << 0.0 << " "
105 << 0.05 << std::endl;
106 else if (&(vector.lattice) == &bc.B)
107 file << 2 << " " << (rotation * vector.cartesian()).transpose() << " " << 0.0 << " "
108 << 0.05 << std::endl;
109 else if (&(vector.lattice) == &bc.csl)
110 file << 3 << " " << (rotation * vector.cartesian()).transpose() << " " << 0.0 << " " << 0.2
111 << std::endl;
112 else
113 file << 4 << " " << (rotation * vector.cartesian()).transpose() << " " << 0.0 << " "
114 << 0.01 << std::endl;
115 } else if (dim == 3) {
116 file << (rotation * 2 * boxVectors[0].cartesian()).transpose() << " ";
117 file << (rotation * boxVectors[1].cartesian()).transpose() << " ";
118 file << (rotation * boxVectors[2].cartesian()).transpose() << " ";
119 file << "\" Properties=atom_types:I:1:pos:R:3:radius:R:1 PBC=\"F T T\" origin=\"";
120 file << (rotation * origin.cartesian()).transpose() << "\"" << std::endl;
121
122 for (const auto &vector: configuration)
123 if (&(vector.lattice) == &bc.A)
124 file << 1 << " " << (rotation * vector.cartesian()).transpose() << " " << 0.05
125 << std::endl;
126 else if (&(vector.lattice) == &bc.B)
127 file << 2 << " " << (rotation * vector.cartesian()).transpose() << " " << 0.05
128 << std::endl;
129 else if (&(vector.lattice) == &bc.csl)
130 file << 3 << " " << (rotation * vector.cartesian()).transpose() << " " << 0.2 << std::endl;
131 else
132 file << 4 << " " << (rotation * vector.cartesian()).transpose() << " " << 0.01
133 << std::endl;
134 }
135 file.close();
136 }
137 return configuration;
138 }
139
140 template<int dim> template<int dm>
141 typename std::enable_if<dm==2,LatticeVector<dim>>::type
143 {
144 LatticeVector<dm> axisAxnA(nA.reciprocalLatticeVector().cross().latticeVector());
145 return (LatticeVector<dm>(bc.getLatticeDirectionInC(axisAxnA).latticeVector()));
146 }
147
148 template<int dim> template<int dm>
149 typename std::enable_if<dm==3,LatticeVector<dim>>::type
151 {
152 assert(abs(nA.cartesian().dot(axis.cartesian())) < FLT_EPSILON);
153 ReciprocalLatticeDirection<dm> axisA(bc.A.reciprocalLatticeVector(axis.cartesian()));
154 LatticeVector<dm> axisAxnA(axisA.reciprocalLatticeVector().cross(nA.reciprocalLatticeVector()).latticeVector());
155 return (LatticeVector<dm>(bc.getLatticeDirectionInC(axisAxnA).latticeVector()));
156 }
157
158
159 template<int dim>
161 {
162 MatrixDimI output;
163 MatrixDimI Q = 2*bc.LambdaA-Eigen::Matrix<IntScalarType,dim,dim>::Identity();
164 auto nC= bc.getReciprocalLatticeDirectionInC(this->nB.reciprocalLatticeVector());
165
168
169 IntScalarType detMN= (bc.M*bc.N).template cast<double>().determinant();
170 Eigen::DiagonalMatrix<IntScalarType,dim> nCDiagonal(nC.reciprocalLatticeVector());
171 RationalMatrix<dim> temp(adjM*adjN*Q*nCDiagonal, Eigen::Matrix<IntScalarType,dim,dim>::Constant(2*detMN));
172
173 IntScalarType alpha= IntegerMath<IntScalarType>::gcd(temp.integerMatrix.diagonal().eval());
174 IntScalarType beta= temp.mu;
176
177 assert(IntegerMath<IntScalarType>::gcd(alpha,beta) == 1);
178
179 //auto basis= bc.dscl.planeParallelLatticeBasis(m,true);
180 auto basis= bc.dscl.planeParallelLatticeBasis(m,false);
181 for(int i=0; i<dim; ++i) {
182 output.col(i) = basis[i].latticeVector();
183 if (i==0) output.col(i)= beta*output.col(i);
184 }
185 return output;
186 }
187
188 template<int dim>
190 {
192 IntScalarType det= basisT.template cast<double>().determinant();
193 // basisTA
194 // T --------> dscl
195 if (&(v.lattice) == &(bc.csl) && IntegerMath<IntScalarType>::gcd(v)%2 == 0)
196 {
197 VectorDimI integerCoordinates= adj * bc.getLatticeVectorInD(v);
198 assert(IntegerMath<IntScalarType>::gcd(integerCoordinates) % det == 0);
199 integerCoordinates= integerCoordinates/det;
200
201 auto temp= LatticeVector<dim>(integerCoordinates,T);
202 if (temp.cartesian().dot(v.cartesian()) < 0) temp= -1*temp;
203 return temp;
204 }
205 else
206 throw(std::runtime_error("The input lattice vector should belong to twice the CSL lattice"));
207
208 }
209
210 template<int dim>
212 {
213 // basisTA
214 // T --------> dscl
215 if (&(v.lattice) == &(bc.dscl))
216 return ReciprocalLatticeVector<dim>((basisT.transpose()*v).eval(),T);
217 else
218 throw(std::runtime_error("The input reciprocal lattice vector should belong to the reciprocal lattice of the DSCL"));
219
220 }
221
222 template<int dim>
227
228 template class Gb<2>;
230 template std::vector<LatticeVector<2>> Gb<2>::box<2>(std::vector<LatticeVector<2>>& boxVectors,
231 const double& orthogonality,
232 const int& dsclFactor,
233 std::string filename,
234 bool orient) const;
235
236 template class Gb<3>;
238 template std::vector<LatticeVector<3>> Gb<3>::box<3>(std::vector<LatticeVector<3>>& boxVectors,
239 const double& orthogonality,
240 const int& dsclFactor,
241 std::string filename,
242 bool orient) const;
243
244 template class Gb<4>;
245 template class Gb<5>;
246}
247
248
249#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:223
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:49
MatrixDimI getBasisT(const BiCrystal< dim > &bc, const ReciprocalLatticeDirection< dim > &n)
Definition Gb.cpp:160
std::enable_if< dm==2, LatticeVector< dim > >::type getPeriodVector(const ReciprocalLatticeVector< dim > &axis) const
Definition Gb.cpp:142
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:39
ReciprocalLatticeVector< dim > getReciprocalLatticeVectorInT(const ReciprocalLatticeVector< dim > &v) const
Definition Gb.cpp:211
LatticeVector< dim > getLatticeVectorInT(const LatticeVector< dim > &v) const
Definition Gb.cpp:189
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)