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
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
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
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)
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
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
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)