Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
GlidePlaneNoiseBase.cpp
Go to the documentation of this file.
1/* This file is part of MoDELib, the Mechanics Of Defects Evolution Library.
2 *
3 *
4 * MoDELib is distributed without any warranty under the
5 * GNU General Public License (GPL) v2 <http://www.gnu.org/licenses/>.
6 */
7
8#ifndef model_GlidePlaneNoiseBase_cpp
9#define model_GlidePlaneNoiseBase_cpp
10
11#include <numbers>
12#include <chrono>
13#include <GlidePlaneNoiseBase.h>
14#include <TerminalColors.h>
15
16namespace model
17{
18
19// Cai's doubly-convoluted spreading function in Fourier space
20template <int N>
22{
23 REAL_SCALAR k = sqrt(kx*kx + ky*ky + kz*kz);
24 if(k>0.0)
25 {
26 return a*k*sqrt(0.5*boost::math::cyl_bessel_k(2,a*k));
27 }
28 else
29 {
30 return 1.;
31 }
32}
33
34// Square of Cai's doubly-convoluted spreading function in Fourier space
35template <int N>
37{
38 const REAL_SCALAR k2(kx*kx + ky*ky + kz*kz);
39 const REAL_SCALAR k(sqrt(k2));
40 if(k2>0.0)
41 {
42 return a*a*k2*0.5*boost::math::cyl_bessel_k(2,a*k);
43 }
44 else
45 {
46 return 1.;
47 }
48}
50// Cai spreading function
51template <int N>
54 return 15.*a*a*a*a/(8.*M_PI*pow(r2+a*a,7./2.));
56
57template <int N>
59{
60 return 0.3425*W_Cai(r2,0.9038*a) + 0.6575*W_Cai(r2,0.5451*a);
61}
62
63template <int N>
65 const int& seed_in,
66 const NoiseTraitsBase::GridSizeType& gridSize_in,
67 const NoiseTraitsBase::GridSpacingType& gridSpacing_in,
68 const Eigen::Matrix<double,2,2>& latticeBasis):
69 /*init*/ UniformPeriodicGrid<2>(gridSize_in.template segment<2>(0),gridSpacing_in.template segment<2>(0))
70 /*init*/,tag(tag_in)
71 /*init*/,seed(seed_in)
72 /*init*/,gridSize(gridSize_in)
73 /*init*/,gridSpacing(gridSpacing_in)
74 /*init*/,gridLength(gridSize.template cast<double>()*gridSpacing)
75 /*init*/,invTransposeLatticeBasis(latticeBasis.transpose().inverse())
76 /*init*/,NX(gridSize(0))
77 /*init*/,NY(gridSize(1))
78 /*init*/,NZ(gridSize(2))
79 /*init*/,NK(NZ>1 ? NX*NY*(NZ/2+1) : NX*(NY/2+1))
80 /*init*/,NR(NX*NY*NZ)
81 /*init*/,LX(gridLength(0))
82 /*init*/,LY(gridLength(1))
83 /*init*/,LZ(gridLength(2))
84{
85}
87template <int N>
90 return *this;
92
93template <int N>
98
99template <int N>
100int GlidePlaneNoiseBase<N>::storageIndex(const int& i,const int& j) const
101{
104 return gridSize(1)*i+j;
105}
106
107#ifdef _MODEL_GLIDE_PLANE_NOISE_GENERATOR_
108
109template <int N>
110std::vector<typename GlidePlaneNoiseBase<N>::COMPLEX*> GlidePlaneNoiseBase<N>::originalKCorrelations() const
111{
112 std::vector<COMPLEX*> okCorr;
113 for(int n=0;n<N;++n)
114 {
115 okCorr.push_back((COMPLEX*) fftw_malloc(sizeof(COMPLEX)*NK));
116 // explicitly initialize to zeros, avoid garbarge propagation
117 std::fill(okCorr[n], okCorr[n]+NK, COMPLEX{0.0, 0.0});
118 }
119
120 const int J_MAX = (NZ > 1) ? NY : (NY/2 + 1);
121 const int K_MAX = (NZ > 1) ? (NZ/2 + 1) : 1 ;
122 for(int i=0; i<NX; i++)
123 {
124 for(int j=0; j<J_MAX; j++)
125 {
126 for(int k=0; k<K_MAX; k++)
127 {
128 // const int ind = NY*(NZ/2+1)*i + j*(NZ/2+1) + k;
129 const int ind = J_MAX*K_MAX*i + j*K_MAX + k;
130
131 REAL_SCALAR kx = 2.*M_PI/LX*REAL_SCALAR(i);
132 if(i>NX/2)
133 {
134 kx = 2.*M_PI/LX*REAL_SCALAR(i-NX);
135 }
136
137 REAL_SCALAR ky = 2*M_PI/LY*REAL_SCALAR(j);
138 if(j>NY/2)
139 {
140 ky = 2.*M_PI/LY*REAL_SCALAR(j-NY);
141 }
142
143 REAL_SCALAR kz = 2.*M_PI/LZ*REAL_SCALAR(k);
144
145 const Eigen::Matrix<double,3,1> kv((Eigen::Matrix<double,3,1>()<<kx,ky,kz).finished());
146 const Eigen::Matrix<int,3,1> kvID((Eigen::Matrix<int,3,1>()<<i,j,k).finished());
147// const double kCorrFactor(NZ>1 ? ((k==0 || k==NZ/2)? 1.0 : 2.0) : ((j==0 || j==NY/2)? 1.0 : 2.0)); // /!\ special case for k=0 and k==NZ/2 because of folding of C2R Fourier transform
148 const auto kCorr(kCorrelations(kv,kvID));
149 for(int n=0;n<N;++n)
150 {
151// okCorr[n][ind]=sqrt(kCorr[n]/kCorrFactor);
152 okCorr[n][ind]=sqrt(kCorr[n]);
153 }
154 }
155 }
156 }
157 return okCorr;
158}
159
160template <int N>
161std::vector<typename GlidePlaneNoiseBase<N>::COMPLEX*> GlidePlaneNoiseBase<N>::noisyKCorrelations(const std::vector<COMPLEX*>& okCorr,
162 std::default_random_engine& generator,
163 std::normal_distribution<REAL_SCALAR>& distribution) const
164{
165 //std::vector<COMPLEX*> nkCorr(okCorr);
166 std::vector<COMPLEX*> nkCorr;
167 for(int n=0;n<N;++n)
168 {
169 nkCorr.push_back((COMPLEX*) fftw_malloc(sizeof(COMPLEX)*NK));
170 // explicitly initialize to zeros, avoid garbarge propagation
171 std::fill(nkCorr[n], nkCorr[n]+NK, COMPLEX{0.0, 0.0});
172 }
173
174 for(int ind=0;ind<NK;++ind)
175 {
176 const REAL_SCALAR Nk = distribution(generator);
177 const REAL_SCALAR Mk = distribution(generator);
178 for(int n=0;n<N;++n)
179 {
180 nkCorr[n][ind]=okCorr[n][ind]*COMPLEX(Nk,Mk)/std::numbers::sqrt2;
181 }
182 }
183
184 for(int n=0;n<N;++n)
185 {
186 nkCorr[n][0]=0;
187 }
188
189 return nkCorr;
190}
191
192template <int N>
193std::vector<typename GlidePlaneNoiseBase<N>::REAL_SCALAR*> GlidePlaneNoiseBase<N>::realNoise(const std::vector<COMPLEX*>& nkCorr) const
194{
195 std::vector<REAL_SCALAR*> rNoise;
196 for(int n=0;n<N;++n)
197 {
198 rNoise.push_back((REAL_SCALAR*) fftw_malloc(sizeof(REAL_SCALAR)*NR));
199 // explicitly initialize to zeros, avoid garbarge propagation
200 std::fill(rNoise[n], rNoise[n]+NR, REAL_SCALAR{0.0});
201 }
202
203 for(int n=0;n<N;++n)
204 {
205 fftw_plan nPlan = (NZ>1 ? fftw_plan_dft_c2r_3d(NX, NY, NZ, reinterpret_cast<fftw_complex*>(nkCorr[n]), rNoise[n], FFTW_ESTIMATE)
206 //: fftw_plan_dft_c2r_2d(NX, NY, reinterpret_cast<fftw_complex*>(nkCorr[n]), rNoise[n], FFTW_ESTIMATE));
207 : fftw_plan_dft_c2r_2d(NY, NX, reinterpret_cast<fftw_complex*>(nkCorr[n]), rNoise[n], FFTW_ESTIMATE));
208 fftw_execute(nPlan);
209 }
210
211 return rNoise;
212}
213#endif
214
215template <int N>
217{
218 std::cout<<greenBoldColor<<"Computing "+tag<<defaultColor<<std::flush;
219 const auto t0= std::chrono::system_clock::now();
220
221#ifdef _MODEL_GLIDE_PLANE_NOISE_GENERATOR_
222
223 std::default_random_engine generator(seed);
224 std::normal_distribution<REAL_SCALAR> distribution(0.0,1.0);
225
226 std::vector<REAL_SCALAR*> rNoise(realNoise(noisyKCorrelations(originalKCorrelations(),generator,distribution)));
227
228 // Store Real noise
229 this->reserve(NX*NY);
230 const int k=0;
231 for(int i=0;i<NX;i++)
232 {
233 for(int j=0;j<NY;j++)
234 {
235 const int ind = NY*NZ*i + j*NZ + k;
236 Eigen::Matrix<REAL_SCALAR,1,N> temp;
237 for(int n=0;n<N;++n)
238 {
239 temp(n)=rNoise[n][ind];
240 }
241 this->push_back(NoiseTraits<N>::fromMatrix(temp));
242 }
243 }
244
245#else
246 this->resize(NX*NY,NoiseTraits<N>::Zero());
247#endif
248 std::cout<<greenColor<<" ["<<(std::chrono::duration<double>(std::chrono::system_clock::now()-t0)).count()<<" sec]"<<defaultColor<<std::endl;
249}
250
251
252template <int N>
253std::vector<std::vector<double>> GlidePlaneNoiseBase<N>::averageNoiseCorrelation(const int& reps) const
254{
255#ifdef _MODEL_GLIDE_PLANE_NOISE_GENERATOR_
256
257 std::normal_distribution<REAL_SCALAR> distribution(0.0,1.0);
258
259 // store original correlations once
260 std::vector<COMPLEX*> okCorr(originalKCorrelations());
261
262 // init storage for average correlation
263 std::vector<COMPLEX*> avgkCorr;
264 for(int n=0; n<N; ++n)
265 {
266 avgkCorr.push_back((COMPLEX*) fftw_malloc(sizeof(COMPLEX) * NK));
267 // Zero-initialize explicitly
268 std::fill(avgkCorr[n], avgkCorr[n]+NK, COMPLEX{0.0, 0.0});
269 }
270
271 for(int k=0;k<reps;++k)
272 {
273 unsigned int seed = k+1;
274 std::default_random_engine generator(seed);
275 // nkCorr is a sampled (randomized) noise in k space
276 const std::vector<COMPLEX*> nkCorr = noisyKCorrelations(okCorr,generator,distribution);
277 for(int n=0;n<N;++n)
278 {
279 for(int ind=0;ind<NK;++ind)
280 {
281 // accumulate power spectrum and ensemble average calculated correaltion
282 const COMPLEX I = nkCorr[n][ind]*std::conj(nkCorr[n][ind]);
283 avgkCorr[n][ind] += I / static_cast<double>(reps);
284 }
285 }
286 }
287
288 // do IDFT from correlation in k-space to real space
289 std::vector<REAL_SCALAR*> avgrCorr(realNoise(avgkCorr));
290
291 // initialize a flattened array for python API
292 std::vector<std::vector<double>> avgrCorrFlat;
293
294 const int k=0;
295 for(int n=0;n<N;++n)
296 {
297 std::vector<double> temp;
298 for(int i=0;i<NX;i++)
299 {
300 for(int j=0;j<NY;j++)
301 {
302 const int ind = NY*NZ*i + j*NZ + k;
303 temp.push_back(avgrCorr[n][ind]);
304 }
305 }
306 avgrCorrFlat.push_back(temp);
307 }
308
309 return avgrCorrFlat;
310
311#endif
312}
313
314template <int N>
315std::vector<std::vector<double>> GlidePlaneNoiseBase<N>::sampleAverageNoise(const int& reps) const
316{
317#ifdef _MODEL_GLIDE_PLANE_NOISE_GENERATOR_
318
319 std::normal_distribution<REAL_SCALAR> distribution(0.0,1.0);
320
321 // store original correlations once
322 std::vector<COMPLEX*> okCorr(originalKCorrelations());
323
324 // init storage for sampled noises
325 std::vector<std::vector<double>> rNoises;
326
327 for(int k=0;k<reps;++k)
328 {
329 unsigned int seed = k+1;
330 std::default_random_engine generator(seed);
331 for(int n=0;n<N;++n)
332 {
333 // nkCorr is a sampled (randomized) noise in k space
334 const std::vector<COMPLEX*> nkNoise = noisyKCorrelations(okCorr,generator,distribution);
335 // sampled noise to real space
336 const std::vector<REAL_SCALAR*> nrNoise(realNoise(nkNoise));
337
338 const int k=0;
339 std::vector<double> temp;
340 for(int i=0;i<NX;i++)
341 {
342 for(int j=0;j<NY;j++)
343 {
344 const int ind = NY*NZ*i + j*NZ + k;
345 temp.push_back(nrNoise[n][ind]);
346 }
347 }
348 rNoises.push_back(temp);
349 }
350 }
351
352 return rNoises;
353
354#endif
355}
356
357template <int N>
359{
360 // Compute Statistics
362 for(const auto& valArr: noiseVector())
363 {
364 ave+=valArr;
365 }
366 ave/=noiseVector().size();
367
369 for(const auto& valArr: noiseVector())
370 {
371 var+=NoiseTraits<N>::squared(valArr-ave);
372 }
373 var/=noiseVector().size();
374
375 std::cout<<"gridSize= "<<gridSize.transpose()<<std::endl;
376 std::cout<<"gridSpacing= "<<gridSpacing.transpose()<<std::endl;
377 std::cout<<"noiseAverage="<<ave*mat.mu_SI<<" [Pa]"<<std::endl;
378 std::cout<<"noiseVariance="<<var*std::pow(mat.mu_SI,2)<<" [Pa^2]"<<std::endl;
379}
380
381// void AnalyticalSolidSolutionNoise::Write_field_slice(REAL_SCALAR *F, const char *fname)
382// {
383// FILE *OutFile=fopen(fname,"w");
384//
385// fprintf(OutFile,"# vtk DataFile Version 2.0\n");
386// fprintf(OutFile,"iter %d\n",0);
387// fprintf(OutFile,"BINARY\n");
388// fprintf(OutFile,"DATASET STRUCTURED_POINTS\n");
389// fprintf(OutFile,"ORIGIN \t %f %f %f\n",0.,0.,0.);
390// fprintf(OutFile,"SPACING \t %f %f %f\n", DX, DY, DZ);
391// fprintf(OutFile,"DIMENSIONS \t %d %d %d\n", NX, NY, 1);
392// fprintf(OutFile,"POINT_DATA \t %d\n",NX*NY);
393// fprintf(OutFile,"SCALARS \t volume_scalars double 1\n");
394// fprintf(OutFile,"LOOKUP_TABLE \t default\n");
395//
396// for(int i=0;i<NX;i++)
397// {
398// for(int j=0;j<NY;j++)
399// {
400// const int k=0;
401// const int ind = NY*NZ*i + j*NZ + k;
402// const double temp=NoiseTraitsBase::ReverseDouble(double(F[ind]));
403// fwrite(&temp, sizeof(double), 1, OutFile);
404// }
405// }
406//
407// fclose(OutFile);
408// }
409
410template struct GlidePlaneNoiseBase<1>;
411template struct GlidePlaneNoiseBase<2>;
412
413}
414#endif
415
The q vector I
a
Definition int_R.m:14
size_t InstanceCount< Derived >::count
static std::string greenColor
static std::string greenBoldColor
static std::string defaultColor
GlidePlaneNoiseBase(const std::string &tag_in, const int &seed_in, const NoiseTraitsBase::GridSizeType &gridSize_in, const NoiseTraitsBase::GridSpacingType &gridSpacing_SI_in, const Eigen::Matrix< double, 2, 2 > &latticeBasis)
int storageIndex(const int &i, const int &j) const
void computeRealNoiseStatistics(const PolycrystallineMaterialBase &mat) const
NoiseTraitsBase::REAL_SCALAR REAL_SCALAR
NoiseTraitsBase::COMPLEX COMPLEX
std::vector< COMPLEX * > noisyKCorrelations(const std::vector< COMPLEX * > &okCorr, std::default_random_engine &generator, std::normal_distribution< REAL_SCALAR > &distribution) const
std::vector< std::vector< double > > sampleAverageNoise(const int &reps) const
NoiseTraits< N >::NoiseContainerType NoiseContainerType
const GridSpacingType gridLength
std::vector< std::vector< double > > averageNoiseCorrelation(const int &reps) const
static REAL_SCALAR Wk_Cai_squared(REAL_SCALAR kx, REAL_SCALAR ky, REAL_SCALAR kz, REAL_SCALAR a)
const NoiseContainerType & noiseVector() const
std::vector< REAL_SCALAR * > realNoise(const std::vector< COMPLEX * > &nkCorr) const
static REAL_SCALAR W_t_Cai(REAL_SCALAR r2, REAL_SCALAR a)
NoiseTraits< N >::NoiseType NoiseType
const Eigen::Matrix< double, 2, 2 > invTransposeLatticeBasis
const GridSpacingType gridSpacing
std::vector< COMPLEX * > originalKCorrelations() const
static REAL_SCALAR W_Cai(REAL_SCALAR r2, REAL_SCALAR a)
static REAL_SCALAR Wk_Cai(REAL_SCALAR kx, REAL_SCALAR ky, REAL_SCALAR kz, REAL_SCALAR a)
virtual std::array< COMPLEX, N > kCorrelations(const Eigen::Matrix< double, 3, 1 > &k, const Eigen::Matrix< int, 3, 1 > &kID) const
Eigen::Array< double, 3, 1 > GridSpacingType
Definition NoiseTraits.h:22
Eigen::Array< int, 3, 1 > GridSizeType
Definition NoiseTraits.h:21
static NoiseType squared(const NoiseType &m)
static NoiseType Zero()
static const NoiseType & fromMatrix(const Eigen::Matrix< REAL_SCALAR, 1, N > &m)
UniformPeriodicGrid(const ArrayDimI &gridSize_in, const ArrayDimD &gridSpacing_in)
int j
REAL t0
int k
int i
vertex temp