-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathpolycrystal.m
More file actions
341 lines (293 loc) · 9.24 KB
/
polycrystal.m
File metadata and controls
341 lines (293 loc) · 9.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
%
%%%%%%%%%%%%%%%%%%%%%%%%%% Polycystal generator %%%%%%%%%%%%%%%%%%%%%%%%
%
% Author: Nikhil Admal %
% Institution: University of California Los Angeles %
% Department: Materials Science and Engineering %
%
% A polycrystal is viewed as a Voronoi tessellation associated with a
% distribution of grain centers and their corresponding random
% orientations.
%
% The program constructs grain centers, and their corresponding random
% orientations for a given
% log-normal distribution for grain sizes. Size of a grain is defined
% as the minimum of the distances between the its center to
% other grain enters.
%
% Program output: The final polycrystal is not outputted as a Voronoi tessellation.
% Instead, it is outputted in the form of a uniform grid, with each grid
% point associated to the closes grid center. Additionally the grains may be
% scaled to form plates/needle-like microstructures.
clear all
close all
clc
% The code has not been tested for dim = 2.
% So do not change the value of dim
dim = 3;
% Scales used to generate different textures such as needles or plates
scalex = 1.0;
scaley = 1.0;
scalez = 1.0;
% nGrains: Number of grains
% Note: This does not mean we end up with 'nGrains' grains.
% The program tries to pack 'nGrains' grains subjected to a given
% distribution of grain size over 'maxit' iterations.
nGrains = 150;
% length of the sample
length = 3e-6;
% Maximum twist about an axis of rotation
maxtwist = 20*pi/180;
% Covergence
maxit = 1000;
% Resolution of the grid to output the polycrystal
ngrid=100;
% The algorithm begins here.
% Variables
% ---------
% ctr...................Counter for number of grains
% grainSize.............An array containing the grain size normalized w.r.t to length
% randPoint.............A random point in the domain chosen from a uniform distribution
% q.....................A random vector describing the orientation of the grain.
% |q| = twist, and q/|q| = dir which is the rotation axis.
% dir is sampled from a uniform distribution on a sphere.
% grain(dimn,nGrans)....Grain centers
% b[]...................Array with entries distribute log normally
%
ctr = 1;
grainSize = zeros(nGrains,1);
b=[];
% Iterate until maxit
for i=1:maxit
% Construct a random point from a uniform distibuion
for j=1:dim
randPoint(j) = rand;
end
% Construct a random orientation vector q
ru=rand;
theta=rand*pi/2;
dir = [sqrt(1-ru^2)*cos(theta);...
sqrt(1-ru^2)*sin(theta);...
ru];
twist = rand*maxtwist;
q=twist*dir;
% If it the first random point, then accept it as the first grain
if (ctr == 1)
grain(:,ctr) = randPoint;
orientation(ctr,:) = q;
if (ctr == nGrains)
break;
end
ctr = ctr+1;
else
% If it is not the first grain center, then measure its distrance to
% existing grain centers and store in the array dist
dist=zeros(ctr-1,1);
for k=1:ctr-1
dist(k)=(randPoint(1)-grain(1,k))^2/scalex^2+...
(randPoint(2)-grain(2,k))^2/scaley^2+...
(randPoint(3)-grain(3,k))^2/scalez^2;
end
dist = sqrt(dist);
% rpoint is a random variable (rv) with a uniform distribution, used to
% generate a rv logcdf^{-1}(x), with a log-normal distribution,
% where logcdf is the cdf of a log-normal distribution
% Note: Keep rpoint away from 0 and 1 as it gets difficult to find
% the roots of logcdf^{-1}(x)-rpoint=0, when rpoints is close to 0
% or 1
rpoint=(0.995-0.0015)*rand+0.0015;
fun=@(x) logcdf(x)-rpoint;
% minDist is a random variable with log-normal distribution
minDist=fzero(fun,0.2);
b=[b;minDist];
% Accept randPoint as the grain center if all the distances to
% existing grid centers are greater than minDist.
if (all(dist > minDist))
grain(:,ctr) = randPoint;
% Once randPoint is accepted as a grid center, associate the
% randorm orientation to it.
orientation(ctr,:) = q;
% If we have reached the 'nGrains' grains, then exit. Else
% iterate.
if (ctr == nGrains)
break;
end
ctr = ctr + 1
end
end
if (i == maxit)
nGrains = ctr-1;
end
end
% Calculate the grain sizes
for i = 1:nGrains
dist=[];
for j = 1:nGrains
if (j ~= i)
dist = [dist; (grain(1,i)-grain(1,j))^2+...
(grain(2,i)-grain(2,j))^2+...
(grain(3,i)-grain(3,j))^2];
end
end
grainSize(i) = sqrt(min(dist));
end
% Compare the pdfs of the actual log normal distribution using 'b' and the
% distribution of grain sizes using 'grainSize' in a histogram plot
figure;
histogram(grainSize(1:nGrains),'BinWidth',0.01,'Normalization','pdf')
hold on;
histogram(b,'BinWidth',0.01,'Normalization','pdf')
tix=get(gca,'xtick')';
set(gca,'xticklabel',num2str(tix,'%.2f'))
tix=get(gca,'ytick')';
set(gca,'yticklabel',num2str(tix,'%.2f'))
% Ourput the voronoi tessellation in the form of a grid
x=[0:1/ngrid:1];
y=[0:1/ngrid:1];
if (dim==2)
[X,Y] = meshgrid(x,y);
elseif (dim==3)
z=[0:1/ngrid:1];
[X,Y,Z] = meshgrid(x,y,z);
end
maxGrainPoints = ngrid^3;
numGrainPoints = zeros(nGrains,1);
for i=1:numel(X)
if (dim == 2)
point = [X(i) Y(i)];
elseif (dim==3)
point = [X(i) Y(i) Z(i)];
end
dist = zeros(nGrains,1);
for j=1:nGrains
for k=1:dim
dist(j) = (point(1)-grain(1,j))^2/scalex^2+...
(point(2)-grain(2,j))^2/scaley^2+...
(point(3)-grain(3,j))^2/scalez^2;
end
end
dist=sqrt(dist);
[minVal,minI] = min(dist);
F1(i) = orientation(minI,1);
F2(i) = orientation(minI,2);
F3(i) = orientation(minI,3);
numGrainPoints(minI) = numGrainPoints(minI)+1;
if (numGrainPoints(minI) > maxGrainPoints)
numGrainPoints(minI)
break;
end
end
F1 = reshape(F1,size(X));
F2 = reshape(F2,size(X));
F3 = reshape(F3,size(X));
% Output the polycrystal in terms of the grid point and associated
% orientation. The output is taylored to be an input file for COMSOL
fid1 = fopen('orientation1.txt','w');
fid2 = fopen('orientation2.txt','w');
fid3 = fopen('orientation3.txt','w');
gridArray = length*[0:1/ngrid:1];
fprintf(fid1,'%s\n', '%grid');
fprintf(fid1,'%.5e ', gridArray);
fprintf(fid1,'\n');
fprintf(fid1,'%.5e ', gridArray);
fprintf(fid1,'\n');
fprintf(fid1,'%.5e ', gridArray);
fprintf(fid1,'\n');
fprintf(fid1,'%s', '%data');
fprintf(fid2,'%s\n', '%grid');
fprintf(fid2,'%.5e ', gridArray);
fprintf(fid2,'\n');
fprintf(fid2,'%.5e ', gridArray);
fprintf(fid2,'\n');
fprintf(fid2,'%.5e ', gridArray);
fprintf(fid2,'\n');
fprintf(fid2,'%s', '%data');
fprintf(fid3,'%s\n', '%grid');
fprintf(fid3,'%.5e ', gridArray);
fprintf(fid3,'\n');
fprintf(fid3,'%.5e ', gridArray);
fprintf(fid3,'\n');
fprintf(fid3,'%.5e ', gridArray);
fprintf(fid3,'\n');
fprintf(fid3,'%s', '%data');
for i=1:ngrid+1
fprintf(fid1,'\n');
fprintf(fid2,'\n');
fprintf(fid3,'\n');
for j=1:ngrid+1
for k=1:ngrid+1
fprintf(fid1,'%6.4f ',F1(k,i,j));
fprintf(fid2,'%6.4f ',F2(k,i,j));
fprintf(fid3,'%6.4f ',F3(k,i,j));
end
end
end
fclose(fid1);
fclose(fid2);
fclose(fid3);
% figure
%
% for i=1:3
%
% scatter3(grainPoints(i,:,1),grainPoints(i,:,2),grainPoints(i,:,3),50,orientation(i,1)*ones(1,maxGrainPoints),'filled');
% xlim([0 1]);
% ylim([0 1]);
% zlim([0 1]);
%
% hold on;
% end
%
% scatter3(grain(1,1:3),grain(2,1:3),grain(3,1:3),100,'red','filled');
% xlim([0 1]);
% ylim([0 1]);
% zlim([0 1]);
% hold on;
%
%
%
% % Plot
% % figure
% % scatter3(pointsArray(1,:),pointsArray(2,:),pointsArray(3,:),25,orientation(:,1),'filled');
% % hold on;
%
% bx = reshape(X(:,:,1),[],1);
% by = reshape(Y(:,:,1),[],1);
% bz = reshape(Z(:,:,1),[],1);
% bF = reshape(F1(:,:,1),[],1);
%
% tx = reshape(X(:,:,ngrid+1),[],1);
% ty = reshape(Y(:,:,ngrid+1),[],1);
% tz = reshape(Z(:,:,ngrid+1),[],1);
% tF = reshape(F1(:,:,ngrid+1),[],1);
%
% lx = reshape(X(1,:,:),[],1);
% ly = reshape(Y(1,:,:),[],1);
% lz = reshape(Z(1,:,:),[],1);
% lF = reshape(F1(1,:,:),[],1);
%
% rx = reshape(X(ngrid+1,:,:),[],1);
% ry = reshape(Y(ngrid+1,:,:),[],1);
% rz = reshape(Z(ngrid+1,:,:),[],1);
% rF = reshape(F1(ngrid+1,:,:),[],1);
%
% fx = reshape(X(:,1,:),[],1);
% fy = reshape(Y(:,1,:),[],1);
% fz = reshape(Z(:,1,:),[],1);
% fF = reshape(F1(:,1,:),[],1);
%
% dx = reshape(X(:,ngrid+1,:),[],1);
% dy = reshape(Y(:,ngrid+1,:),[],1);
% dz = reshape(Z(:,ngrid+1,:),[],1);
% dF = reshape(F1(:,ngrid+1,:),[],1);
%
% scatter3(bx,by,bz,50,bF,'filled');
% hold on;
% scatter3(tx,ty,tz,50,tF,'filled');
% hold on;
% scatter3(lx,ly,lz,50,lF,'filled');
% hold on;
% scatter3(rx,ry,rz,50,rF,'filled');
% hold on;
% scatter3(fx,fy,fz,50,fF,'filled');
% hold on;
% scatter3(dx,dy,dz,50,dF,'filled');