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)
Example #2
0
    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()
Example #3
0
    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)
Example #4
0
    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()