oILAB
Loading...
Searching...
No Matches
GbMesoStateImplementation.h
Go to the documentation of this file.
1//
2// Created by Nikhil Chandra Admal on 5/27/24.
3//
4
5#ifndef OILAB_GBMESOSTATEIMPLEMENTATION_H
6#define OILAB_GBMESOSTATEIMPLEMENTATION_H
7
8#include<Lammps.h>
9#include <iostream>
10//#include <Python.h>
12
13namespace gbLAB {
14 template<int dim>
17 const std::deque<std::tuple<LatticeVector<dim>,VectorDimD,int>>& bs,
18 const std::vector<LatticeVector<dim>>& mesoStateCslVectors,
19 const BicrystalLatticeVectors& bicrystalConfig)
20 try :
21 GbContinuum<dim>(getMesoStateGbDomain(mesoStateCslVectors),
22 get_xuPairs(gb,mesoStateCslVectors,bs),
23 discretize(mesoStateCslVectors,gb),
24 bicrystalCoordsMap(gb,bicrystalConfig)),
25 gb(gb),
26 axis(axis),
27 mesoStateCslVectors(mesoStateCslVectors),
28 bicrystalConfig(bicrystalConfig),
29 bs(bs)
30 {
31 // check
32 /*
33 auto xuPairs= get_xuPairs(bs);
34 for(const auto& pair : xuPairs)
35 std::cout << (pair.second-this->displacement(pair.first)).norm() << std::endl;
36 */
37 }
38 catch(std::runtime_error& e)
39 {
40 //throw(std::runtime_error("GB Mesostate construction failed"));
41 }
42
43
44 template<int dim>
45 Eigen::Matrix<double, dim,dim-1> GbMesoState<dim>::getMesoStateGbDomain(const std::vector<LatticeVector<dim>>& mesoStateCslVectors)
46 {
47 Eigen::Matrix<double, dim,dim-1> mesoStateGbDomain;
48 for(int i=1; i<dim; ++i)
49 mesoStateGbDomain.col(i-1)= mesoStateCslVectors[i].cartesian();
50 return mesoStateGbDomain;
51 }
52
53 template<int dim>
54 std::map<OrderedTuplet<dim+1>, typename GbMesoState<dim>::VectorDimD>
56 const std::vector<LatticeVector<dim>>& mesoStateCslVectors,
57 const std::deque<std::tuple<LatticeVector<dim>,VectorDimD,int>>& bs)
58 {
59 auto normal= gb.nA.cartesian().normalized();
60 std::map<OrderedTuplet<dim+1>,VectorDimD> xuPairs;
61 std::vector<LatticeVector<dim>> bicrystalBoxVectors(mesoStateCslVectors);
62 bicrystalBoxVectors[0]= 2*mesoStateCslVectors[0];
63 VectorDimD shift;
64 shift << -0.5-FLT_EPSILON,-FLT_EPSILON,-FLT_EPSILON;
65
66
67 for(const auto& [b,s,include] : bs)
68 {
70 VectorDimD valueu;
71 // value = b/2
72 valueu= b.cartesian()/2;
73 VectorDimD tempx= s-valueu;
74
75
76 /*
77 if(tempx.dot(normal)<FLT_EPSILON) // tempx is in lattice A
78 {
79 // modulo tempx w.r.t the bicrystal box
80 LatticeVector<dim>::modulo(tempx,bicrystalBoxVectors,shift);
81 try {
82 keyx << gb.bc.getLatticeVectorInD(gb.bc.A.latticeVector(tempx)),1;
83 }
84 catch(std::runtime_error& e)
85 {
86 std::cout << e.what() << std::endl;
87 std::cout << "x key = " << keyx.transpose() << "; " << tempx.transpose() << std::endl;
88 std::cout << "b = " << b.cartesian().transpose() << " ; s= " << s.transpose() << std::endl;
89 exit(0);
90 }
91
92 }
93 else // tempx is in lattice B
94 {
95 tempx= tempx + 2*valueu.dot(normal) * normal;
96 // modulo tempx w.r.t the bicrystal box
97 LatticeVector<dim>::modulo(tempx,bicrystalBoxVectors,shift);
98
99 try {
100 keyx << gb.bc.getLatticeVectorInD(gb.bc.B.latticeVector(tempx)),2;
101 }
102 catch(std::runtime_error& e)
103 {
104 std::cout << e.what() << std::endl;
105 std::cout << "x key = " << keyx.transpose() << "; " << tempx.transpose() << std::endl;
106 std::cout << "b = " << b.cartesian().transpose() << " ; s= " << s.transpose() << std::endl;
107 exit(0);
108 }
109
110 }
111 */
112 // modulo tempx w.r.t the bicrystal box
113 LatticeVector<dim>::modulo(tempx,bicrystalBoxVectors,shift);
114 try {
115 if (tempx.dot(normal) < FLT_EPSILON) // tempx is in lattice A
116 keyx << gb.bc.getLatticeVectorInD(gb.bc.A.latticeVector(tempx)), 1;
117 else // tempx is in lattice B region
118 keyx << gb.bc.getLatticeVectorInD(gb.bc.A.latticeVector(tempx)), -1;
119 }
120 catch(std::runtime_error& e) {
121 std::cout << e.what() << std::endl;
122 std::cout << "x key = " << keyx.transpose() << "; " << tempx.transpose() << std::endl;
123 std::cout << "b = " << b.cartesian().transpose() << " ; s= " << s.transpose() << std::endl;
124 exit(0);
125 }
126 xuPairs[keyx]=valueu;
127 }
128 if(xuPairs.size() != bs.size())
129 throw(std::runtime_error("Clash in constraints."));
130 return xuPairs;
131 }
132
133 template<int dim>
134 std::array<Eigen::Index,dim-1> GbMesoState<dim>::discretize(const std::vector<LatticeVector<dim>>& mesoStateCslVectors, const Gb<dim>& gb)
135 {
136 std::array<Eigen::Index,dim-1> n{};
137 for(int i=1; i<dim; ++i)
138 n[i-1]= 10*ceil(mesoStateCslVectors[i].cartesian().norm()/gb.bc.A.latticeBasis.col(0).norm());
139 //n[i-1]= 4*IntegerMath<int>::gcd(gb.bc.getLatticeVectorInD(mesoStateCslVectors[i]));
140 return n;
141
142 }
143
144
145 template<int dim>
146 std::map<OrderedTuplet<dim+1>,typename GbMesoState<dim>::VectorDimD> GbMesoState<dim>::bicrystalCoordsMap(const Gb<dim>& gb, const BicrystalLatticeVectors& bicrystalConfig)
147 {
148 std::map<OrderedTuplet<dim+1>,VectorDimD> idCoordsMap;
149
150 for(const auto& latticeVector : bicrystalConfig) {
151 auto latticeVectorInD= gb.bc.getLatticeVectorInD(latticeVector);
153 if (&latticeVector.lattice == &gb.bc.A) {
154 if (latticeVector.dot(gb.nA) <= 0)
155 key << latticeVectorInD, 1;
156 else
157 key << latticeVectorInD, -1;
158 }
159 else if (&latticeVector.lattice == &gb.bc.B) {
160 if (latticeVector.dot(gb.nB) <= 0)
161 key << latticeVectorInD, 2;
162 else
163 key << latticeVectorInD, -2;
164 }
165 idCoordsMap[key]= latticeVectorInD.cartesian();
166 }
167 return idCoordsMap;
168
169 }
170
171 /*-------------------------------------*/
172 template<int dim>
173 std::tuple<double,double,PeriodicFunction<double,dim>> GbMesoState<dim>::densityEnergy(const std::string& lmpLocation,
174 const std::string& potentialName,
175 bool relax,
176 const std::array<Eigen::Index,dim>& n) const
177 {
178 box("temp" + std::to_string(omp_get_thread_num()));
179 std::pair<double,double> densityEnergyPair= energy(lmpLocation,
180 "temp" + std::to_string(omp_get_thread_num()) + "_reference1.txt",
181 potentialName);
182
183
184 // the columns of rhoCell defined the box in which rho is calculated
185 Eigen::Matrix3d rhoCell;
186 PeriodicFunction<double,dim> rho(n,rhoCell);
187 for (int i=0; i<n[0]; ++i)
188 {
189 for (int j=0; j<n[1]; ++j) {
190 for (int k = 0; k < n[2]; ++k)
191 {
192 Eigen::Vector<double,Eigen::Dynamic> x= i*rho.unitCell.col(0)/n[0] +
193 j*rho.unitCell.col(1)/n[1] +
194 k*rho.unitCell.col(2)/n[2];
195 // rho(i,j,k) is the density at point x
196 // calculate rho by first reading the relaxed configuration
197
198 }
199 }
200
201 }
202
203 return {densityEnergyPair.first,densityEnergyPair.second,rho};
204
205 }
206
207
208 /*-------------------------------------*/
209 /*
210 template<int dim>
211 std::pair<double,double> GbMesoState<dim>::densityEnergyPython() const
212 {
213 // form box
214 // run a python script to calculate energy
215
216 setenv("PYTHONPATH", ".", 1);
217 if(!Py_IsInitialized()) {
218 std::cout << "Initializing Python Interpreter" << std::endl;
219 Py_Initialize();
220 }
221
222 box("temp");
223 PyObject* pyModuleString = PyUnicode_FromString((char*)"lammps");
224 PyObject* pyModule = PyImport_Import(pyModuleString);
225 if (pyModule == nullptr)
226 {
227 PyErr_Print();
228 std::cout << "cannot import python script" << std::endl;
229 std::exit(0);
230 }
231 PyObject* pDict = PyModule_GetDict(pyModule);
232 PyObject* pyFunction= PyDict_GetItemString(pDict, (char*)"energy");
233 //PyObject* pyEnergy= PyObject_CallObject(pyFunction,NULL);
234 PyObject* pyValue= PyObject_CallObject(pyFunction,NULL);
235 double energy, density;
236
237 PyArg_ParseTuple(pyValue, "dd", &energy, &density);
238 //double energy= PyFloat_AsDouble(pyEnergy);
239
240 Py_DECREF(pyModule);
241 Py_DECREF(pyModuleString);
242
243 return std::make_pair(density,energy);
244 }
245 */
246
247 template<int dim>
248 //template<int dm=dim>
249 typename std::enable_if<dim==3,void>::type
250 GbMesoState<dim>::box(const std::string& name) const
251 {
252 const auto& config= this->bicrystalConfig;
253 std::vector<LatticeVector<3>> boxVectors;
254 boxVectors.push_back(this->mesoStateCslVectors[0]);
255 boxVectors.push_back(this->mesoStateCslVectors[1]);
256 boxVectors.push_back(this->mesoStateCslVectors[2]);
257
258 std::vector<VectorDimD> referenceConfigA, deformedConfigA;
259 std::vector<VectorDimD> referenceConfigB, deformedConfigB;
260 std::vector<VectorDimD> configDscl;
261
262 double bmax= 0.0;
263 for(const auto& [b,s,include] : bs)
264 bmax= max(bmax,b.cartesian().norm());
265
266 int numberOfIgnoredPoints= 0;
267 for (const auto &latticeVector: config) {
268 VectorDimD x;
270 if (&(latticeVector.lattice) == &(this->gb.bc.A)) {
271 double height= latticeVector.cartesian().dot(gb.nA.cartesian().normalized());
272 if (height<FLT_EPSILON)
273 temp << gb.bc.getLatticeVectorInD(latticeVector),1;
274 else
275 temp << gb.bc.getLatticeVectorInD(latticeVector),-1;
276 }
277 else if (&(latticeVector.lattice) == &(this->gb.bc.B)) {
278 double height = latticeVector.cartesian().dot(gb.nB.cartesian().normalized());
279 if (height<FLT_EPSILON)
280 temp << gb.bc.getLatticeVectorInD(latticeVector),2;
281 else
282 temp << gb.bc.getLatticeVectorInD(latticeVector),-2;
283 }
284
285 //x = latticeVector.cartesian() + this->displacement(latticeVector.cartesian());
286
287 if (&(latticeVector.lattice) == &(this->gb.bc.A)) {
288 x = latticeVector.cartesian() + this->displacement(temp) + this->uAverage;
289 }
290 else if (&(latticeVector.lattice) == &(this->gb.bc.B) )
291 x = latticeVector.cartesian() + this->displacement(temp) - this->uAverage;
292 else
293 x = latticeVector.cartesian() + this->displacement(temp);
294
295 // ignore x if it occupies a deleted CSL position
296 bool ignore= false;
297 VectorDimD cslShift;
298 cslShift << -0.5, -FLT_EPSILON, -FLT_EPSILON;
299 VectorDimD xModulo= x;
300 std::vector<LatticeVector<3>> localBoxVectors(boxVectors);
301 localBoxVectors[0]=5*boxVectors[0];
302 LatticeVector<dim>::modulo(xModulo, localBoxVectors, cslShift);
303 for(const auto& [b,s, include] : bs) {
304 if (include == 2 && (s - xModulo).norm() < 1e-6) {
305 ignore = true;
306 numberOfIgnoredPoints++;
307 break;
308 }
309 }
310 if (ignore==true) {
311 continue;
312 }
313
314
315 if (&(latticeVector.lattice) == &(this->gb.bc.A) && x.dot(this->gb.nA.cartesian().normalized()) <= 1e-6)
316 //if (&(latticeVector.lattice) == &(this->gb.bc.A) && x.dot(this->gb.nA.cartesian().normalized()) <= FLT_EPSILON)
317 //if (&(latticeVector.lattice) == &(this->gb.bc.A))
318 {
319 referenceConfigA.push_back(latticeVector.cartesian());
320 deformedConfigA.push_back(x);
321 }
322 else if (&(latticeVector.lattice) == &(this->gb.bc.B) && x.dot(this->gb.nB.cartesian().normalized()) <= 1e-6)
323 //else if (&(latticeVector.lattice) == &(this->gb.bc.B) && x.dot(this->gb.nB.cartesian().normalized()) <= FLT_EPSILON)
324 //else if (&(latticeVector.lattice) == &(this->gb.bc.B))
325 {
326 referenceConfigB.push_back(latticeVector.cartesian());
327 deformedConfigB.push_back(x);
328 }
329
330 }
331
332
333 int numberOfIgnoredCSLPoints= 0;
334 for(const auto& [b,s, include] : bs)
335 {
336 if (include==2) numberOfIgnoredCSLPoints++;
337 }
338 if(numberOfIgnoredPoints != 2*numberOfIgnoredCSLPoints)
339 throw(std::runtime_error("GB Mesostate construction failed: incorrect number of points"));
340
341
342 int nAtoms= referenceConfigA.size()+referenceConfigB.size()+configDscl.size();
343
344 std::string referenceFile= name + "_reference0.txt";
345 std::string deformedFile= name + "_reference1.txt";
346
347 std::ofstream reference, deformed;
348 reference.open(referenceFile);
349 deformed.open(deformedFile);
350 if (!reference || !deformed) std::cerr << "Unable to open files";
351 reference << nAtoms << std::endl; deformed << nAtoms << std::endl;
352 reference << "Lattice=\" "; deformed << "Lattice=\" ";
353
354 reference << std::setprecision(15) << (2*boxVectors[0].cartesian()).transpose() << " ";
355 deformed << std::setprecision(15) << (2*boxVectors[0].cartesian()).transpose() << " ";
356 reference << std::setprecision(15) << (boxVectors[1].cartesian()).transpose() << " ";
357 deformed << std::setprecision(15) << (boxVectors[1].cartesian()).transpose() << " ";
358 reference << std::setprecision(15) << (boxVectors[2].cartesian()).transpose();
359 deformed << std::setprecision(15) << (boxVectors[2].cartesian()).transpose();
360 reference << "\" Properties=atom_types:I:1:pos:R:3:radius:R:1 PBC=\"F T T\" origin=\" "; deformed << "\" Properties=atom_types:I:1:pos:R:3:radius:R:1 PBC=\" F T T\" origin=\" ";
361 reference << std::setprecision(15) << (-1 * boxVectors[0].cartesian()).transpose() << "\"" << std::endl;
362 deformed << std::setprecision(15) << (-1 * boxVectors[0].cartesian()).transpose() << "\"" << std::endl;
363
364 for(const auto& position : referenceConfigA)
365 reference << 1 << " " << std::setprecision(15) << position.transpose() << " " << 0.05 << std::endl;
366 for(const auto& position : referenceConfigB)
367 reference << 2 << " " << std::setprecision(15) << position.transpose() << " " << 0.05 << std::endl;
368 for(const auto& position : deformedConfigA)
369 deformed << 1 << " " << std::setprecision(15) << position.transpose() << " " << 0.05 << std::endl;
370 for(const auto& position : deformedConfigB)
371 deformed << 2 << " " << std::setprecision(15) << position.transpose() << " " << 0.05 << std::endl;
372 for(const auto& position : configDscl) {
373 reference << 4 << " " << std::setprecision(15) << position.transpose() << " " << 0.01 << std::endl;
374 deformed << 4 << " " << std::setprecision(15) << position.transpose() << " " << 0.01 << std::endl;
375 }
376
377 reference.close();
378 deformed.close();
379 }
380
381}
382
383#endif
std::pair< double, double > energy(const std::string &lammpsLocation, const std::string &oilabConfigFile, const std::string &potentialFile)
Definition Lammps.h:244
Definition Gb.h:16
const ReciprocalLatticeDirection< dim > nA
Definition Gb.h:33
const BiCrystal< dim > & bc
Definition Gb.h:29
const ReciprocalLatticeDirection< dim > nB
Definition Gb.h:37
static Eigen::Matrix< double, dim, dim-1 > getMesoStateGbDomain(const std::vector< LatticeVector< dim > > &mesoStateCslVectors)
Returns the cartesian coordinates of the CSL vectors that define a mesostate's GB.
GbMesoState(const Gb< dim > &gb, const ReciprocalLatticeVector< dim > &axis, const std::deque< std::tuple< LatticeVector< dim >, VectorDimD, int > > &bs, const std::vector< LatticeVector< dim > > &mesoStateCslVectors, const BicrystalLatticeVectors &bicrystalConfig)
std::enable_if< dim==3, void >::type box(const std::string &filename) const
std::vector< LatticeVector< dim > > BicrystalLatticeVectors
Definition GbMesoState.h:22
static std::map< OrderedTuplet< dim+1 >, VectorDimD > get_xuPairs(const Gb< dim > &gb, const std::vector< LatticeVector< dim > > &mesoStateCslVectors, const std::deque< std::tuple< LatticeVector< dim >, VectorDimD, int > > &bs)
Returns the displacement constraints for the GB continuum model from the translation-shift pairs def...
std::tuple< double, double, PeriodicFunction< double, dim > > densityEnergy(const std::string &lmpLocation, const std::string &potentialName, bool relax, const std::array< Eigen::Index, dim > &n=std::array< Eigen::Index, dim >{}) const
Calculate the energy of a mesostate using lammps.
typename LatticeCore< dim >::VectorDimD VectorDimD
Definition GbMesoState.h:21
static std::map< OrderedTuplet< dim+1 >, VectorDimD > bicrystalCoordsMap(const Gb< dim > &gb, const BicrystalLatticeVectors &bicrystalConfig)
Returns the Cartesian coordinates of the lattice vectors of the mesostates's bicrystal in the form of...
static std::array< Eigen::Index, dim-1 > discretize(const std::vector< LatticeVector< dim > > &mesoStateCslVectors, const Gb< dim > &gb)
Returns the discretization of the grain boundary domain.
LatticeVector class.
static std::enable_if< dm==2, void >::type modulo(LatticeVector< dim > &input, const std::vector< LatticeVector< dim > > &basis, const VectorDimD &shift=VectorDimD::Zero())
const Eigen::Matrix< double, Eigen::Dynamic, dim > unitCell