def __init__(self, midpoint, rot_matrix, r, k, d_eq): self.r = r self.k = k self.d_eq = d_eq self.L = (1/k * 8/3. * (2*r+1)**3 / ((r**2+4*r+1)*(r+1)) * 4*np.pi/3)**(1/3.) * d_eq * 0.5 self.a_long = 1/(2*r+1) * self.L self.a_short = r * self.a_long self.H = np.sqrt(3)/2 * self.L self.h = (r+1)/(2*r+1) * self.H self.t = k*self.h self.circumcircle = np.sqrt((self.a_long/2.)**2 + (self.H/3.)**2 + (self.t/2.)**2) self.rot_matrix = rot_matrix self.rot_matrix_tr = np.ascontiguousarray(rot_matrix.transpose()) angle, axis = GeometryTools.rotmatrix_to_axisangle(rot_matrix) self.rot_axis = axis self.rot_angle = angle self.euler_angles = GeometryTools.rotmatrix_to_euler(rot_matrix) self.basal_area = self.H*self.L/2. - 3*np.sqrt(3)/4 * self.a_short**2 self.volume = self.basal_area*self.t # vertices in coordinates of the triangle if r > 0: self.vertices = np.array([[self.a_long/2, -self.H/3, -self.t/2], [self.a_long/2 + self.a_short/2, np.sqrt(3)/2*self.a_short - self.H/3, -self.t/2], [self.a_short/2, self.h - self.H/3, -self.t/2], [-self.a_short/2, self.h - self.H/3, -self.t/2], [-self.a_long/2 - self.a_short/2, np.sqrt(3)/2*self.a_short - self.H/3, -self.t/2], [-self.a_long/2, -self.H/3, -self.t/2]]) else: self.vertices = np.array([[self.L/2, -self.H/3, -self.t/2], [0, 2*self.H/3, -self.t/2], [-self.L/2, -self.H/3, -self.t/2]]) self.set_midpoint(midpoint)
def prepare_triangles(vol_frac_goal, L, r_d, k_d, d_eq_d): """ Prepares a list of truncated prisms from the given distributions. :param vol_frac_goal: Goal volume fraction. :param L: Size of window. :param r_d: Distribution (callback function) for r, truncation size. :param k_d: Distribution (callback function) for k, elongation factor. :param d_eq_d: Distribution (callback function) for d, equivalent diameter. :return: List of prisms which contain random locations and a random r, k, and d. """ print("Prepare triangles") trunc_triangles = list() total_volume = L**3 volume = 0. # Make random grains while volume < vol_frac_goal * total_volume: midpoint = L * np.random.random(3) r = r_d() k = k_d() d_eq = d_eq_d() rot_matrix = GeometryTools.random_rotation() trunc_triangle = tt.TruncatedTriangle(midpoint, rot_matrix, r, k, d_eq) trunc_triangles.append(trunc_triangle) volume += trunc_triangle.volume return trunc_triangles
def compute_all_misorientation_voxel(trunc_triangles, grain_ids, M): """ Computes misorientation distribution using grain_ids to find grain boundaries. """ print 'Computing voxel based misorientation' symOps=[] # Unity symOps.append(np.eye(3)) # 3 fold axis around z symOps.append(GT.rot_matrix([0,0,1],2*math.pi/3)) symOps.append(GT.rot_matrix([0,0,-1],2*math.pi/3)) # 2 fold axis around (sqrt(3),-1,0) symOps.append(GT.rot_matrix([math.sqrt(3),-1,0],math.pi)) # 2 fold axis around y symOps.append(GT.rot_matrix([0,1,0],math.pi)) # 2 fold axis around (sqrt(3),1,0) symOps.append(GT.rot_matrix([math.sqrt(3),1,0],math.pi)) from collections import defaultdict areas = defaultdict(int) angles = defaultdict(float) for ix in range(M[0]): nx = (ix + 1) % M[0] for iy in range(M[1]): ny = (iy + 1) % M[1] for iz in range(M[2]): nz = (iz + 1) % M[2] ig = grain_ids[ix + iy * M[0] + iz * (M[0] * M[1])] if ig == 1: continue # Skip the Co-phase def do_compute(ng): if ig != ng and ng != 1: index = (min(ig, ng), max(ig, ng)) areas[index] += 1 if index not in angles: angles[index] = compute_misorientation_net(trunc_triangles[ig-2], trunc_triangles[ng-2], symOps) # Check all three neighbours (in the + side) do_compute(grain_ids[nx + iy * M[0] + iz * (M[0] * M[1])]) do_compute(grain_ids[ix + ny * M[0] + iz * (M[0] * M[1])]) do_compute(grain_ids[ix + iy * M[0] + nz * (M[0] * M[1])]) return angles, areas
def compute_misorientation_net(t1,t2,symmetry=[]): """ Computes the misorientation between two truncated triangles t1 and t2. """ R1=t1.rot_matrix R2=t2.rot_matrix R2inv = np.linalg.inv(R2) net_rotation=np.dot(R1,R2inv) if len(symmetry)==0: theta,axis = GT.rotmatrix_to_axisangle(net_rotation) return theta*180/math.pi else: angles=[] for i in xrange(len(symmetry)): for j in xrange(len(symmetry)): theta,axis = GT.rotmatrix_to_axisangle( np.dot( np.dot(symmetry[i],R1),np.dot(R2inv,symmetry[j]))) angles.append(theta*180/math.pi) return np.min(angles)
def compute_all_misorientation_net(trunc_triangles,nbrList): symOps=[] # Unity symOps.append(np.eye(3)) # 3 fold axis around z symOps.append(GT.rot_matrix([0,0,1],2*math.pi/3)) symOps.append(GT.rot_matrix([0,0,-1],2*math.pi/3)) # 2 fold axis around (sqrt(3),-1,0) symOps.append(GT.rot_matrix([math.sqrt(3),-1,0],math.pi)) # 2 fold axis around y symOps.append(GT.rot_matrix([0,1,0],math.pi)) # 2 fold axis around (sqrt(3),1,0) symOps.append(GT.rot_matrix([math.sqrt(3),1,0],math.pi)) angles=[] for i,t in enumerate(trunc_triangles): for j in xrange(len(nbrList[i])): theta = compute_misorientation_net(t,trunc_triangles[ nbrList[i][j] ],symOps) angles.append(theta) return angles
def compute_all_misorientation_net(trunc_triangles, nbrList): """ Computes misorientation given a list of trunc_triangles and a neighborList Using the net rotation M_1^-1 * M_2, with a few symmetry operations. This method might not be correct. """ symOps = [] # Unity symOps.append(np.eye(3)) # 3 fold axis around z symOps.append(GT.rot_matrix([0, 0, 1], 2*math.pi/3)) symOps.append(GT.rot_matrix([0, 0, -1], 2*math.pi/3)) # 2 fold axis around y symOps.append(GT.rot_matrix([0, 1, 0], math.pi)) angles = [] print('Computing misorientation angles net') for i, t in enumerate(trunc_triangles): for j in xrange(len(nbrList[i])): theta = compute_misorientation_net(t, trunc_triangles[nbrList[i][j]], symOps) angles.append(theta) return angles
def prepare_triangles(vol_frac_goal, L, r_min=0.1, r_max=0.4, k_min=0.2, k_max=0.6): """ Prepares random truncated_triangle objects. Grains are generated until the vol_frac_goal is exceeded. Geometry parameters r,k,d and rotation matrix are drawn from uniform distributions. Returns the list of truncated triangles sorted by size. """ print "Prepare triangles" d_eq_min = 0.5 d_eq_max = 2 trunc_triangles = [] total_volume = L**3 volume = 0. # Make random grains while volume/total_volume < vol_frac_goal: midpoint = L*np.random.random(3) r = (r_max-r_min)*np.random.random() + r_min k = (k_max-k_min)*np.random.random() + k_min d_eq = (d_eq_max-d_eq_min)*np.random.random() + d_eq_min rot_matrix = GeometryTools.random_rotation() trunc_triangle = tt.TruncatedTriangle(midpoint, rot_matrix, r, k, d_eq) trunc_triangles.append(trunc_triangle) volume += trunc_triangle.volume # Sort triangles w.r.t. volume, so that large triangles are added to the box first trunc_triangles.sort(key=lambda m: m.volume, reverse=True) return trunc_triangles