def strain_energy(): C_al3Mg = np.array([[0.64, 0.24, 0.24, 0, 0, 0], [0.24, 0.64, 0.24, 0, 0, 0], [0.24, 0.24, 0.64, 0, 0, 0], [0, 0, 0, 0.65, 0, 0], [0, 0, 0, 0, 0.65, 0], [0, 0, 0, 0, 0, 0.65]]) C_al = np.array([[0.63, 0.41, 0.41, 0, 0, 0], [0.41, 0.63, 0.41, 0, 0, 0], [0.41, 0.41, 0.63, 0, 0, 0], [0, 0, 0, 0.43, 0, 0], [0, 0, 0, 0, 0.43, 0], [0, 0, 0, 0, 0, 0.43]]) C_al = np.array([[0.62639459, 0.41086487, 0.41086487, 0, 0, 0], [0.41086487, 0.62639459, 0.41086487, 0, 0, 0], [0.41086487, 0.41086487, 0.62639459, 0, 0, 0], [0, 0, 0, 0.42750351, 0, 0], [0, 0, 0, 0, 0.42750351, 0], [0, 0, 0, 0, 0, 0.42750351]]) eigenstrain = [0.023, 0.023, 0.023, 0.0, 0.0, 0.0] mu_al = 0.34876 mu_al3mg = 0.20835377082353254 poisson = 0.5*(mu_al + mu_al3mg) poisson = mu_al strain_energy = StrainEnergy(eigenstrain=eigenstrain, poisson=poisson) print(strain_energy.is_isotropic(C_al)) energy = strain_energy.strain_energy(C_matrix=C_al, C_prec=C_al3Mg) v_per_atom = 16.60753125 print(energy*1000.0*v_per_atom) print(energy*1000.0)
def explore_orientations(): from cemc.tools import StrainEnergy from matplotlib import pyplot as plt mu = 0.27155342515650893 C_al = C_al = np.array([[0.62639459, 0.41086487, 0.41086487, 0, 0, 0], [0.41086487, 0.62639459, 0.41086487, 0, 0, 0], [0.41086487, 0.41086487, 0.62639459, 0, 0, 0], [0, 0, 0, 0.42750351, 0, 0], [0, 0, 0, 0, 0.42750351, 0], [0, 0, 0, 0, 0, 0.42750351]]) C_al = np.loadtxt("data/C_al.csv", delimiter=",") C_mgsi = np.loadtxt("data/C_MgSi100_225.csv", delimiter=",") misfit = np.array([[0.0440222, 0.00029263, 0.0008603], [0.00029263, -0.0281846, 0.00029263], [0.0008603, 0.00029263, 0.0440222]]) strain_eng = StrainEnergy(poisson=mu, misfit=misfit) ellipsoid = { "aspect": [10.0, 1.0, 1.0], "C_prec": C_mgsi #"scale_factor": 0.8 } res = strain_eng.explore_orientations( ellipsoid, C_al, step=5, phi_ax="z", fname="data/mgsi100_orientation_needle_iso.csv") strain_eng.plot_explore_result(res) plt.show()
def test_equiv_strain_needle(self): """Test the equivalent strains for a needle.""" if not available: self.skipTest(reason) mu = 0.3 misfit = [0.05, 0.04, 0.03, 0.03, 0.02, 0.01] strain_eng = StrainEnergy(aspect=[50000.0, 5.0, 5.0], eigenstrain=misfit, poisson=mu) f = 9.0 eq_strain = strain_eng.equivalent_eigenstrain(f) kato = kato_et_al_needle(f, mu, misfit) self.assertTrue(np.allclose(eq_strain, kato, atol=1E-3))
def plot(self, princ_misfit=[0.1, 0.1, 0.1], theta=0.0, phi=0.0, show=True): from matplotlib import pyplot as plt from cemc.tools import rot_matrix_spherical_coordinates from cemc.tools import rotate_tensor scale_factors = np.logspace(-3, 3, 100) # Sphere aspects = { "Sphere": [1.0, 1.0, 1.0], "Needle": [10000.0, 1.0, 1.0], "Plate": [10000.0, 10000.0, 1.0] } fig = plt.figure() ax1 = fig.add_subplot(1, 1, 1) colors = ["#5D5C61", "#7395AE", "#B1A296"] color_count = 0 for k, v in aspects.items(): strain_tensor = np.diag(princ_misfit) rot_matrix = rot_matrix_spherical_coordinates(phi, theta) strain_tensor = rotate_tensor(strain_tensor, rot_matrix) strain = StrainEnergy(aspect=v, misfit=strain_tensor, poisson=self.poisson) energy = [ strain.strain_energy(C_matrix=self.tensor, scale_factor=f) for f in scale_factors ] ax1.plot(scale_factors, energy, label=k, color=colors[color_count % 3]) color_count += 1 ax1.set_xscale("log") ax1.set_yscale("log") ax1.spines["right"].set_visible(False) ax1.spines["top"].set_visible(False) ax1.set_xlabel("Scale factor") ax1.set_ylabel("Strain energy") ax1.legend(frameon=False) if show: plt.show()
def test_equiv_strain_plate(self): """Test the equivalent strains for a plate.""" if not available: self.skipTest(reason) mu = 0.3 misfit = [0.05, 0.04, 0.03, 0.03, 0.02, 0.01] strain_eng = StrainEnergy(aspect=[200000000.0, 51200000.0, 0.001], misfit=misfit, poisson=mu) f = 4.0 eq_strain = strain_eng.equivalent_eigenstrain(C_matrix=C_al, scale_factor=f) kato = kato_et_al_plate(f, mu, misfit) self.assertTrue(np.allclose(eq_strain, kato, atol=1E-3))
def test_equiv_strain_sphere(self): """Test the equivalent eigenstrain against analytic results. Kato, M.; Fujii, T. & Onaka, S. Elastic strain energies of sphere, plate and needle inclusions Materials Science and Engineering: A, Elsevier, 1996, 211, 95-103 """ if not available: self.skipTest(reason) mu = 0.3 misfit = [0.05, 0.04, 0.03, 0.03, 0.02, 0.01] strain_eng = StrainEnergy(aspect=[2.0, 2.0, 2.0], eigenstrain=misfit, poisson=mu) f = 5.0 eq_strain = strain_eng.equivalent_eigenstrain(f) kato_et_al = kato_et_al_sphere(f, mu, misfit) self.assertTrue(np.allclose(eq_strain, kato_et_al, atol=1E-5))
def explore_orientations(): from cemc.tools import StrainEnergy from matplotlib import pyplot as plt mu = 0.27155342515650893 C_al = np.loadtxt("data/C_al.csv", delimiter=",") C_mgsi = np.loadtxt("data/C_beta_eye.csv", delimiter=",") misfit = np.array([[ 6.31232839e-02, 2.96796703e-07, 0.00000000e+00], [ 2.96796703e-07, 6.31232839e-02, 0.00000000e+00], [ 0.00000000e+00, 0.00000000e+00, -6.80589135e-05]]) strain_eng = StrainEnergy(poisson=mu, misfit=misfit) ellipsoid = { "aspect": [10000.0, 1.0, 1.0], "C_prec": C_mgsi #"scale_factor": 0.8 } res = strain_eng.explore_orientations( ellipsoid, C_al, step=5, phi_ax="z") strain_eng.plot_explore_result(res) plt.show()
def __call__(self, system_changes): self.cov_obs(system_changes) inertia_tensor = np.trace( self.cov_obs.cov_matrix) * np.eye(3) - self.cov_obs.cov_matrix principal, rot_matrix = np.linalg.eigh(inertia_tensor) # The rotation to be applied to the material properties # and the misfit, is the transpose of the eigenvector # matrix C_mat = rotate_rank4_mandel(self.C_matrix, rot_matrix.T) C_prec = rotate_rank4_mandel(self.C_prec, rot_matrix.T) misfit = rotate_tensor(self.misfit, rot_matrix.T) axes = self.ellipsoid_axes(principal) str_eng = StrainEnergy(aspect=axes, misfit=misfit, poisson=self.poisson) str_energy = str_eng.strain_energy(C_matrix=C_mat, C_prec=C_prec) # Bias potential should not alter the observer # The MC object will handle this self.cov_obs.undo_last() return str_energy * ellipsoid_volume(axes)
G = el.shear_modulus(mode=mode) / GPa E = el.youngs_modulus(mode=mode) / GPa mu = el.poisson_ratio print("Bulk modulus: {} GPa".format(B)) print("Shear modulus: {} GPa".format(G)) print("Poisson ratio: {}".format(mu)) print("Young's modulus {} GPa".format(E)) eigenstrain_princ = [-0.06497269, -0.06497269, 0.09606948, 0.0, 0.0, 0.0] #eigenstrain_princ = [-0.06497269, -0.06497269, 0.04, 0.0, 0.0, 0.0] eigenstrain = [ -0.01129197, -0.01129197, -0.01129197, 0.05368072, 0.05368072, 0.05368072 ] strain_eng = StrainEnergy(poisson=mu, eigenstrain=eigenstrain) ellipsoid = {"aspect": [1000.0, 1.0, 1.0], "scale_factor": 0.83} # strain_eng.explore_aspect_ratios(0.83, C) res = strain_eng.explore_orientations(ellipsoid, C, step=5) # opt_res = strain_eng.optimize_rotation(ellipsoid, C, res[0]["rot_seq"]) # strain_eng.show_ellipsoid(ellipsoid, res[0]["rot_seq"]) strain_eng.plot_explore_result(res) # print(opt_res) # fig = strain_eng.plot(0.83, C, rot_seq=res[0]["rot_seq"]) # fig = strain_eng.plot(0.83, C, rot_seq=res[0]["rot_seq"], latex=True) plt.show() elif eigenstrain: ref_atoms = bulk("Al") ref_atoms *= (2, 2, 2) ref_cell = ref_atoms.get_cell().T strained_cell = atoms.get_cell().T
def optimal_orientation(self, princ_misfit=[0.1, 0.1, 0.1], aspect=[1.0, 1.0, 1.0], scale=1.0, show_map=True): """Find the optimial orientation of the ellipsoid.""" from itertools import product from cemc.tools import rot_matrix_spherical_coordinates from cemc.tools import rotate_tensor from scipy.interpolate import griddata from matplotlib import pyplot as plt # Quick exploration of the space theta = np.linspace(0.0, np.pi / 2.0, 100) phi = np.linspace(0.0, np.pi / 2.0, 100) energy = [] all_theta = [] all_phi = [] for ang in product(phi, theta): strain_tensor = np.diag(princ_misfit) rot_matrix = rot_matrix_spherical_coordinates(ang[0], ang[1]) strain_tensor = rotate_tensor(strain_tensor, rot_matrix) strain = StrainEnergy(aspect=aspect, misfit=strain_tensor, poisson=self.poisson) new_energy = strain.strain_energy(C_matrix=self.tensor, scale_factor=scale) energy.append(new_energy) all_theta.append(ang[1]) all_phi.append(ang[0]) # Locate the minimal energy min_indx = np.argmin(energy) theta_min = all_theta[min_indx] phi_min = all_phi[min_indx] if theta_min > np.pi / 2.0: theta_min = np.pi - theta_min print("Min. energy: {}. Theta: {} Phi. {}" "".format(energy[min_indx], int(theta_min * 180 / np.pi), int(phi_min * 180 / np.pi))) print("Poisson ratio: {}".format(self.poisson)) T, P = np.meshgrid(theta, phi) data = griddata(np.vstack((all_theta, all_phi)).T, energy, (T, P)) fig = plt.figure() ax = fig.add_subplot(1, 1, 1) im = ax.imshow(data.T, origin="lower", aspect="auto", cmap="inferno", extent=[0, 90, 0, 90]) cbar = fig.colorbar(im) cbar.set_label("Strain energy") ax.set_xlabel("Polar angle (deg)") ax.set_ylabel("Azimuthal angle (deg)") if show_map: plt.show()