1 /*!
2  * \file   src/NUMODIS/Crystallo.cxx
3  * \brief
4  * \author Laurent Dupuy
5  * \date   9/06/2017
6  * \copyright Copyright (C) 2006-2018 CEA/DEN, EDF R&D. All rights
7  * reserved.
8  * This project is publicly released under either the GNU GPL Licence
9  * or the CECILL-A licence. A copy of thoses licences are delivered
10  * with the sources of TFEL. CEA or EDF may also distribute this
11  * project under specific licensing conditions.
12  */
13 
14 #include <stdexcept>
15 #include <sstream>
16 #include <vector>
17 #include <string>
18 
19 #include "TFEL/Raise.hxx"
20 #include "NUMODIS/Math/Utilities.hxx"
21 #include "NUMODIS/GSystem.hxx"
22 #include "NUMODIS/Crystallo.hxx"
23 
24 namespace numodis
25 {
26 
27   Crystallo::Crystallo() = default;
28 
29   Crystallo::Crystallo(Crystallo&&) = default;
30 
31   Crystallo::Crystallo(const Crystallo&) = default;
32 
33   //===============================================================
34   // Crystallo::InitGSystem
35   //---------------------------------------------------------------
36   //! Construct a crystallographic verified glide system
37   //---------------------------------------------------------------
38   /*!
39     \param iburgers a Burgers vector
40     \param iplane a glide plane
41     \return a glide system
42   */
43   //===============================================================
InitGSystem(const IBurgers & iburgers,const IPlane & iplane) const44   GSystem Crystallo::InitGSystem(const IBurgers& iburgers,
45 				 const IPlane& iplane) const
46   {
47     if (this->ScalProduct(iplane,iburgers)!=0){
48       std::ostringstream os;
49       os << "Crystallo::InitGSystem: ill-defined glide system"
50 	 << "'" << iburgers << iplane << "'";
51       tfel::raise(os.str());
52     }
53     return GSystem(iburgers,iplane);
54   }
55 
direction(const IDirection & idirection) const56   Vect3 Crystallo::direction(const IDirection& idirection) const
57   {
58     // rotation
59     Vect3 xdirection;
60     for(unsigned i=0; i<_alattice.size(); i++){
61       xdirection+=static_cast<double>(idirection.getIndex()[i])*_alattice[i];
62     }
63     // convert to a unit vector
64     xdirection.Normalize();
65     return xdirection;
66   }
67 
68 
normal(const IPlane & iplane) const69   Vect3 Crystallo::normal(const IPlane& iplane) const
70   {
71     // rotation
72     Vect3 xdirection;
73     for(unsigned i=0; i<this->_alattice.size(); i++)
74       xdirection+=static_cast<double>(iplane[i])*(this->_plattice[i]);
75     // convert to a unit vector
76     xdirection.Normalize();
77     return xdirection;
78   }
79 
burgers_vector(const IBurgers & iburgers) const80   Vect3 Crystallo::burgers_vector(const IBurgers& iburgers) const
81   {
82     Vect3 xburgers;
83     for(unsigned i=0; i<_blattice.size(); i++){
84       xburgers+=static_cast<double>(iburgers.getIndex()[i])*_blattice[i];
85     }
86     return xburgers;
87   }
88 
89   //=====================================================================
90   // Crystallo::ComputeJunctionGSystem
91   //---------------------------------------------------------------------
92   //! Compute the glide system of a junction between two glide systems
93   //---------------------------------------------------------------------
94   /*!
95     \param gsystem1 first glide system
96     \param gsystem2 second glide system
97     \return output glide system
98   */
99   //=====================================================================
ComputeJunctionGSystem(const GSystem & gsystem1,const GSystem & gsystem2) const100   GSystem Crystallo::ComputeJunctionGSystem(const GSystem& gsystem1,
101 					    const GSystem& gsystem2) const
102   {
103 
104     // same glide plane?
105     if(gsystem1.getIPlane()==gsystem2.getIPlane())
106       {
107 
108 	if(Coincide(gsystem1.getIBurgers(),gsystem2.getIBurgers())!=0)
109 	  {
110 
111 	    // self junction
112 	    throw -1;
113 	  }
114 	else
115 	  {
116 	    // add Burgers vectors
117 	    IBurgers iburgers3a(gsystem1.getIBurgers()+gsystem2.getIBurgers());
118 	    IBurgers iburgers3b(gsystem1.getIBurgers()-gsystem2.getIBurgers());
119 
120 	    // consider the smallest one
121 	    IBurgers ijunctionBurgers( this->Norm2(iburgers3a)<this->Norm2(iburgers3b) ? iburgers3a : iburgers3b );
122 
123 	    // return new glide system
124 	    return this->InitGSystem(ijunctionBurgers,gsystem1.getIPlane());
125 	  }
126       }
127     else {
128       if(Coincide(gsystem1.getIBurgers(),gsystem2.getIBurgers())!=0){
129 	// colinear situation
130 	throw -2;
131       }
132       // compute junction direction
133       IDirection ijunction(this->getNindices());;
134       this->CrossProduct(gsystem1.getIPlane(),gsystem2.getIPlane(),ijunction);
135 
136       // add Burgers vectors
137       IBurgers iburgers3a(gsystem1.getIBurgers()+gsystem2.getIBurgers());
138       IBurgers iburgers3b(gsystem1.getIBurgers()-gsystem2.getIBurgers());
139 
140       // consider the smallest
141       Vect3 xjunction  = this->direction(ijunction);
142       Vect3 xburgers3a = this->burgers_vector(iburgers3a);
143       Vect3 xburgers3b = this->burgers_vector(iburgers3b);
144       double E3a = xburgers3a.SquareLength()*(1-0.3*pow(xjunction.Dot(xburgers3a.UnitVector()),2));
145       double E3b = xburgers3b.SquareLength()*(1-0.3*pow(xjunction.Dot(xburgers3b.UnitVector()),2));
146 
147       IBurgers ijunctionBurgers( E3a<E3b ? iburgers3a : iburgers3b );
148 
149       // compute the glide plane
150       IPlane ijunctionPlane(this->getNindices());
151       this->CrossProduct(ijunctionBurgers,ijunction,ijunctionPlane);
152 
153       // return new glide system
154       return this->InitGSystem(ijunctionBurgers,ijunctionPlane);
155     }
156   }
157 
158   //=====================================================================
159   // Crystallo::GenerateEquivalentGSystems
160   //---------------------------------------------------------------------
161   //! Provide a vector of all equivalent glide systems
162   //---------------------------------------------------------------------
163   /*!
164     \param gsystem reference glide system
165     \param allGSystems all equivalet glide systems
166   */
167   //=====================================================================
GenerateEquivalentGSystems(const GSystem & gsystem,std::vector<GSystem> & allGSystems) const168   void Crystallo::GenerateEquivalentGSystems(const GSystem& gsystem,
169 					     std::vector<GSystem>& allGSystems) const
170   {
171 
172     // generate all planes
173     std::vector<IPlane> allPlanes;
174     this->GenerateEquivalentPlanes(gsystem.getIPlane(),allPlanes);
175 
176     // generate all the other Burgers vector
177     std::vector<IBurgers> allBurgers;
178     this->GenerateEquivalentIBurgers(gsystem.getIBurgers(),allBurgers);
179 
180     // generate all glide systems
181     for(decltype(allPlanes.size()) i=0; i!=allPlanes.size(); i++)
182       for(decltype(allBurgers.size()) j=0; j!=allBurgers.size(); j++)
183 	if(this->ScalProduct(allPlanes[i],allBurgers[j])==0)
184 	  allGSystems.push_back(GSystem(allBurgers[j],allPlanes[i]));
185 
186   }
187 
188   //===============================================================
189   // Crystallo::SameGlideSystem
190   //---------------------------------------------------------------
191   //! Determines a glide system belongs to a given familly
192   //---------------------------------------------------------------
193   /*!
194     This routine determines whether a glide system defined as
195     \f${iplane1}[iburgers1]\f$ belongs to a glide system family
196     defined as \f${iburgers0}<iburgers0>\f$.
197 
198     This routine is virtual. By default, this routine does not
199     include any symetry.
200 
201     \param iplane0 reference glide system
202     \param iburgers0 reference burgers vector
203     \param iplane1 a specific glide system
204     \param iburgers1 a specific burgers vector
205     \return true if \f$()[]\f$ belongs to \f${}<>\f$
206   */
207   //===============================================================
SameGlideSystem(const IPlane & iplane0,const IBurgers & iburgers0,const IPlane & iplane1,const IBurgers & iburgers1) const208   bool Crystallo::SameGlideSystem(const IPlane& iplane0,
209 				  const IBurgers& iburgers0,
210 				  const IPlane& iplane1,
211 				  const IBurgers& iburgers1) const
212   {
213     return (iplane1==iplane0 && Coincide(iburgers0,iburgers1)!=0);
214   }
215 
216   //=====================================================================
217   // Crystallo::GenerateEquivalentIBurgers
218   //---------------------------------------------------------------------
219   //! Provide a list of IBurgers equivalent to a given IBurgers
220   //---------------------------------------------------------------------
221   /*!
222     \param iburgers original IBurgers
223     \param planes equivalent IBurgers
224   */
225   //=====================================================================
GenerateEquivalentIBurgers(const IBurgers & iburgers,std::vector<IBurgers> & eqiburgers) const226   void Crystallo::GenerateEquivalentIBurgers(const IBurgers& iburgers,
227 					     std::vector<IBurgers>& eqiburgers) const
228   {
229 
230     //----------------
231     // initialization
232     //----------------
233     std::vector<int> indices(iburgers.getIndex());
234     std::vector<std::vector<int> > equivalent;
235 
236     //-----------------------------
237     // generate equivalent indices
238     //-----------------------------
239     this->GenerateEquivalentIndices(indices,equivalent);
240 
241     //---------------------
242     // convert to iburgers
243     //---------------------
244     eqiburgers.clear();
245     eqiburgers.reserve(equivalent.size());
246     for(unsigned i=0; i<equivalent.size(); i++)
247       eqiburgers.push_back(IBurgers(equivalent[i]));
248 
249   }
250 
251   //=====================================================================
252   // Crystallo::GenerateEquivalentPlanes
253   //---------------------------------------------------------------------
254   //! Provide a list of IPlanes equivalent to a given IPlane
255   //---------------------------------------------------------------------
256   /*!
257     \param iplane original IPlane
258     \param planes equivalent iplanes
259   */
260   //=====================================================================
GenerateEquivalentPlanes(const IPlane & iplane,std::vector<IPlane> & planes) const261   void Crystallo::GenerateEquivalentPlanes(const IPlane& iplane,
262 					   std::vector<IPlane>& planes) const
263   {
264 
265     //----------------
266     // initialization
267     //----------------
268     std::vector<int> indices(iplane.getIndex());
269     std::vector<std::vector<int> > equivalent;
270 
271     //-----------------------------
272     // generate equivalent indices
273     //-----------------------------
274     this->GenerateEquivalentIndices(indices,equivalent);
275 
276     //-------------------
277     // convert to planes
278     //-------------------
279     planes.clear();
280     planes.reserve(equivalent.size());
281     for(unsigned i=0; i<equivalent.size(); i++)
282       planes.push_back(IPlane(equivalent[i]));
283 
284   }
285 
286   Crystallo::~Crystallo() = default;
287 
288 } // end of namespace numodis
289