def in_plane_indices(normal, magnitude=1, decimal_places=5): """ Returns an array of Miller indices which lie in the plane specified by a surface normal vector. The magnitude specifies the maximum magnitude of the Miller indice searched. """ indices = all_miller_indices(magnitude) return indices[np.where( np.round(normalize(indices).dot(normal), decimal_places) == 0)]
def euler_step(dt, m, torque): """Takes one step using the Euler method dt: time step m: moment unit vector torque: function to calculate torque from m """ t = torque(m) return normalize(m + dt * t)
def rk23_step(dt, m, torque): """ Takes one step using the Bogacki-Shampine method (Runga-Kutta RK23) dt: time step m: moment unit vector torque: function to calculate torque from m """ k1 = torque(m) k2 = torque(m + dt * k1 / 2.0) k3 = torque(m + 3.0 * dt * k2 / 2.0) m = m + 2.0 * dt * k1 / 9.0 + dt * k2 / 3.0 + 4 * dt * k3 / 9.0 return normalize(m)
def huen_step(dt, m, torque): """ Takes one step using Huen's method dt: time step m: moment unit vector torque: function to calculate torque from m """ k1 = torque(m) m1 = m + dt * k1 k2 = torque(m1) m = m + dt * (k1 + k2) / 2.0 return normalize(m)
def in_plane_indices_and_angles(start, normal, rotation='right', magnitude=1, decimal_places=5): """ Returns the Miller indices and angles in degrees for in-plane directions, based on a surface normal and a starting vector in the plane """ indices = in_plane_indices(normal, magnitude, decimal_places) angles = angle_between_directions(start, normal, normalize(indices)) mask = angles.argsort() return in_plane_indices[mask], angles[mask]
def rk4_step(dt, m, torque): """ Takes one step using the Classic 4th order Runga-Kutta method dt: time step m: moment unit vector torque: function to calculate torque from m """ k1 = torque(m) k2 = torque(m + dt * k1 / 2.0) k3 = torque(m + dt * k2 / 2.0) k4 = torque(m + dt * k3) m = m + dt * (k1 + 2.0 * k2 + 2.0 * k3 + k4) / 6.0 return normalize(m)