Ejemplo n.º 1
0
    def fit_modulus(self,
                    moduli: numpy.ndarray,
                    order: int = 2) -> numpy.ndarray:
        '''Interpolate static elastic constants :math:`c^\\text{st}_{ij}(V)` as
        a function of volume with polynomial least square fitting

        :param moduli: The static elastic moduli :math:`c^\\text{st}_{ij}(V)`
            to be fitted
        :param order: The order for least square fitting

        :returns: The interpolated modulus :math:`c^\\text{st}_{ij}(V)`
        '''
        # c_of_v = scipy.interpolate.UnivariateSpline(
        #     numpy.flip(self.volumes, axis=0),
        #     numpy.flip(moduli, axis=0)
        # )
        # return c_of_v(self.v_array)

        strains = calculate_eulerian_strain(self.volumes[0], self.volumes)
        strain_array = calculate_eulerian_strain(self.volumes[0], self.v_array)
        _, modulus_array = polynomial_least_square_fitting(strains,
                                                           moduli,
                                                           strain_array,
                                                           order=order)
        return modulus_array
Ejemplo n.º 2
0
def calibrate_energy_on_reference(volumes_before_calibration: Matrix,
                                  energies_before_calibration: Matrix,
                                  order: Optional[int] = 3):
    """
    In multi-configuration system calculation, the volume set of each calculation may vary a little,
    This function would make the volume set of the first configuration (normally, the most populated configuration)
    as a reference volume set, then calibrate the energies of all configurations to this reference volume set.

    :param volumes_before_calibration: Original volume sets of all configurations
    :param energies_before_calibration: Free energies of all configurations on the original volume sets.
    :param order: The order of Birch--Murnaghan EOS fitting.
    :return: Free energies of each configuration on the
        referenced volumes (usually the volumes of the first configuration).
    """
    configurations_amount, _ = volumes_before_calibration.shape
    volumes_for_reference: Vector = volumes_before_calibration[0]

    energies_after_calibration = np.empty(volumes_before_calibration.shape)
    for i in range(configurations_amount):
        strains_before_calibration = calculate_eulerian_strain(
            volumes_before_calibration[i, 0], volumes_before_calibration[i])
        strains_after_calibration = calculate_eulerian_strain(
            volumes_before_calibration[i, 0], volumes_for_reference)
        _, energies_after_calibration[i, :] = polynomial_least_square_fitting(
            strains_before_calibration,
            energies_before_calibration[i],
            strains_after_calibration,
            order=order)
    return energies_after_calibration
Ejemplo n.º 3
0
def get_static_p_of_v(v_sparse,
                      f_sparse,
                      v0=None,
                      N=100,
                      order=3,
                      v_ratio=1.2) -> callable:

    v0 = v0 if v0 != None else v_sparse[numpy.argmin(f_sparse)]
    x_sparse = calculate_eulerian_strain(v0, v_sparse)
    x_dense = numpy.linspace(
        calculate_eulerian_strain(v0,
                                  numpy.max(v_sparse) * v_ratio),
        calculate_eulerian_strain(v0,
                                  numpy.min(v_sparse) / v_ratio), N + 1)
    _, f_dense = polynomial_least_square_fitting(x_sparse,
                                                 f_sparse,
                                                 x_dense,
                                                 order=order)
    v_dense = from_eulerian_strain(v0, x_dense)
    p_dense = -numpy.gradient(f_dense) / numpy.gradient(v_dense)

    def static_p_of_v(v_new: numpy.array) -> numpy.array:
        x_new = calculate_eulerian_strain(v0, v_new)
        return InterpolatedUnivariateSpline(x_dense, p_dense)(x_new)

    return static_p_of_v
Ejemplo n.º 4
0
    def _calculate_pressure_static(self, order: int = 3):

        volumes = numpy.array(
            [volume.volume for volume in self.qha_input.volumes])
        static_energies = numpy.array(
            [volume.energy for volume in self.qha_input.volumes])

        strains = calculate_eulerian_strain(volumes[0], volumes)
        strain_array = calculate_eulerian_strain(volumes[0], self.v_array)
        _, static_energy_array = polynomial_least_square_fitting(
            strains, static_energies, strain_array, order=order)

        self.static_p_array = -numpy.gradient(
            static_energy_array) / numpy.gradient(self.v_array)
Ejemplo n.º 5
0
    def fit_modulus(self, moduli: numpy.ndarray, order: int = 2) -> numpy.ndarray:
        '''Interpolate static elastic constants :math:`c^\\text{st}_{ij}(V)` as
        a function of volume with polynomial least square fitting

        :param moduli: The static elastic moduli :math:`c^\\text{st}_{ij}(V)`
            to be fitted
        :param order: The order for least square fitting

        :returns: The interpolated modulus :math:`c^\\text{st}_{ij}(V)`
        '''

        strains = calculate_eulerian_strain(self.volumes[0], self.volumes)
        strain_array = calculate_eulerian_strain(self.volumes[0], self.v_array)
        p = numpy.polyfit(strains, self.volumes * moduli, deg = order + 1)
        modulus_array = numpy.polyval(p, strain_array) / self.v_array
        return modulus_array
Ejemplo n.º 6
0
    def fit_modulus(volumes: numpy.ndarray,
                    v_array: numpy.ndarray,
                    moduli: numpy.ndarray,
                    order: int = 2) -> numpy.ndarray:
        '''Interpolate static elastic constants :math:`c^\\text{st}_{ij}(V)` as
        a function of volume with polynomial least square fitting

        :param moduli: The static elastic moduli :math:`c^\\text{st}_{ij}(V)`
            to be fitted
        :param order: The order for least square fitting

        :returns: The interpolated modulus :math:`c^\\text{st}_{ij}(V)`
        '''

        strains = calculate_eulerian_strain(volumes[0], volumes)
        strain_array = calculate_eulerian_strain(volumes[0], v_array)
        _, modulus_array = polynomial_least_square_fitting(strains,
                                                           moduli,
                                                           strain_array,
                                                           order=order)
        return modulus_array
Ejemplo n.º 7
0
 def static_p_of_v(v_new: numpy.array) -> numpy.array:
     x_new = calculate_eulerian_strain(v0, v_new)
     return InterpolatedUnivariateSpline(x_dense, p_dense)(x_new)