from dataclasses import dataclass
import numpy as np
from pathlib import Path
from spyice.utils.error_norms import ErrorNorms
[docs]
@dataclass
class AnalysisData:
"""Represents the analysis data.
Attributes:
all_variables (dict): A dictionary containing all the variables.
"""
all_variables: dict
[docs]
class Analysis:
"""Represents an analysis object that performs error analysis on temperature differences."""
[docs]
def __init__(self, t_k_diff, t_stefan_diff):
"""
Args:
t_k_diff (float): The temperature difference in Kelvin.
t_stefan_diff (float): The temperature difference in Stefan-Boltzmann units.
"""
self.t_k_diff = t_k_diff
self.t_stefan_diff = t_stefan_diff
[docs]
def set_analysis(self):
"""Sets up the analysis for the current object.
This method initializes the `error_norms_object` attribute with an instance of the `ErrorNorms` class,
passing the `t_k_diff` and `t_stefan_diff` attributes as arguments. It then calculates the numerical
analytical difference using the `numerical_analytical_diff` method of the `error_norms_object`.
Args:
None
Returns:
None
"""
self.error_norms_object = ErrorNorms(self.t_k_diff, self.t_stefan_diff)
self.num_ana_temperature_diff = (
self.error_norms_object.numerical_analytical_diff()
)
[docs]
def error_analytical_numerical(self):
"""Calculates the errors of Numerical and Analytical using error norms one, two and infinity.
Args:
None
Returns:
tuple: A tuple containing the errors calculated using different error norms:
- T_k_Stefan_diff_L1norm (float): L1 norm of the difference between T_k_list and T_Stefan_list.
- T_k_Stefan_diff_infnorm (float): Infinity norm of the difference between T_k_list and T_Stefan_list.
- T_k_Stefan_diff_L2norm (float): L2 norm of the difference between T_k_list and T_Stefan_list.
- T_Stefan_diff_L1norm (float): L1 norm of the difference between consecutive T_Stefan values.
- T_Stefan_diff_infnorm (float): Infinity norm of the difference between consecutive T_Stefan values.
- T_Stefan_diff_L2norm (float): L2 norm of the difference between consecutive T_Stefan values.
- T_k_diff_infnorm (float): Infinity norm of the difference between consecutive T_k values.
- T_k_diff_L2norm (float): L2 norm of the difference between consecutive T_k values.
- T_k_diff_L1norm (float): L1 norm of the difference between consecutive T_k values.
"""
# Calculates the errors of Numerical and Analytical using error norms one, two and infinity
# norm(|T_k_list - T_Stefan_list|)
self.num_ana_temperature_diff = self.num_ana_temperature_diff
T_k_Stefan_diff_L1norm, T_k_Stefan_diff_infnorm, T_k_Stefan_diff_L2norm = (
self.calculate_errors(
self.num_ana_temperature_diff, self.error_norms_object
)
)
# Calculates the errors of Analytical temperature differences between two consecutive iterations
# norm(|T_Stefan[i+1] - T_Stefan[i]|)
T_Stefan_diff_L1norm, T_Stefan_diff_infnorm, T_Stefan_diff_L2norm = (
self.calculate_errors(self.t_stefan_diff, self.error_norms_object)
)
# Calculates the errors of Numerical temperature differences between two consecutive iterations
# norm(|T_k[i+1] - T_k[i]|)
T_k_diff_infnorm, T_k_diff_L2norm, T_k_diff_L1norm = self.calculate_errors(
self.t_k_diff, self.error_norms_object
)
self.store_field_errors(
T_k_Stefan_diff_L1norm,
T_k_Stefan_diff_infnorm,
T_k_Stefan_diff_L2norm,
T_Stefan_diff_infnorm,
T_Stefan_diff_L2norm,
T_Stefan_diff_L1norm,
T_k_diff_infnorm,
T_k_diff_L2norm,
T_k_diff_L1norm,
)
[docs]
def calculate_errors(self, field_array, error_norms_object):
"""Calculates the errors of a given field array using the provided error norms object.
Args:
field_array (numpy.ndarray): The field array to calculate the errors for.
error_norms_object (ErrorNorms): The error norms object used to calculate the errors.
Returns:
tuple: A tuple containing the one-norm error, infinity-norm error, and two-norm error.
"""
one_norm_error = error_norms_object.one_norm(field_array)
infinity_norm_error = error_norms_object.infinity_norm(field_array)
two_norm_error = error_norms_object.two_norm(field_array)
return one_norm_error, infinity_norm_error, two_norm_error
[docs]
def store_field_errors(
self,
T_k_Stefan_diff_L1norm,
T_k_Stefan_diff_infnorm,
T_k_Stefan_diff_L2norm,
T_Stefan_diff_infnorm,
T_Stefan_diff_L2norm,
T_Stefan_diff_L1norm,
T_k_diff_infnorm,
T_k_diff_L2norm,
T_k_diff_L1norm,
):
"""Stores the field errors.
Args:
T_k_Stefan_diff_L1norm (float): The L1 norm of the temperature and concentration difference.
T_k_Stefan_diff_infnorm (float): The infinity norm of the temperature and concentration difference.
T_k_Stefan_diff_L2norm (float): The L2 norm of the temperature and concentration difference.
T_Stefan_diff_infnorm (float): The infinity norm of the temperature difference.
T_Stefan_diff_L2norm (float): The L2 norm of the temperature difference.
T_Stefan_diff_L1norm (float): The L1 norm of the temperature difference.
T_k_diff_infnorm (float): The infinity norm of the temperature and concentration difference.
T_k_diff_L2norm (float): The L2 norm of the temperature and concentration difference.
T_k_diff_L1norm (float): The L1 norm of the temperature and concentration difference.
"""
self.T_k_Stefan_diff_L1norm = T_k_Stefan_diff_L1norm
self.T_k_Stefan_diff_infnorm = T_k_Stefan_diff_infnorm
self.t_k_stefan_diff_l2norm = T_k_Stefan_diff_L2norm
self.t_stefan_diff_infnorm = T_Stefan_diff_infnorm
self.t_stefan_diff_l2norm = T_Stefan_diff_L2norm
self.t_stefan_diff_l1norm = T_Stefan_diff_L1norm
self.t_k_diff_infnorm = T_k_diff_infnorm
self.t_k_diff_l2norm = T_k_diff_L2norm
self.t_k_diff_l1norm = T_k_diff_L1norm
[docs]
@classmethod
def get_error_results(
cls,
t_k_diff: np.ndarray,
t_stefan_diff: np.ndarray,
residual: np.ndarray,
temperature_mushy: np.ndarray,
phi_mushy: np.ndarray,
salinity_mushy: np.ndarray,
output_dir: Path | str,
) -> AnalysisData:
"""Runs error analysis on the given temperature differences.
Args:
cls: The class object.
t_k_diff: The temperature difference for k.
t_stefan_diff: The temperature difference for Stefan.
Returns:
AnalysisData: An instance of the AnalysisData class containing the error analysis results.
"""
# print("Running error analysis...")
error_analysis_object = cls(t_k_diff, t_stefan_diff)
error_analysis_object.set_analysis()
error_analysis_object.error_analytical_numerical()
error_analysis_object.export_residuals(
residual, temperature_mushy, phi_mushy, salinity_mushy, output_dir
)
all_vars = dict(vars(error_analysis_object))
return cls.set_dataclass(all_vars, AnalysisData)
[docs]
@staticmethod
def set_dataclass(data_to_be_converted: dict, dataclass: dataclass):
"""Sets the values of a dataclass object using a dictionary.
Args:
data_to_be_converted (dict): A dictionary containing the values to be set.
dataclass (dataclass): The dataclass object to be updated.
Returns:
dataclass: The updated dataclass object.
"""
for key, value in data_to_be_converted.items():
setattr(dataclass, key, value)
return dataclass
[docs]
def export_residuals(
self, residuals: list, temperature_mushy, phi_mushy, salinity_mushy, output_dir
):
"""Exports the residuals to a file.
Args:
residuals (np.array): The residuals to export.
output_dir (str): The output directory to save the residuals to.
Returns:
None
"""
residuals = np.array(residuals, dtype=object)
temperature_mushy = np.array(temperature_mushy, dtype=object)
phi_mushy = np.array(phi_mushy, dtype=object)
salinity_mushy = np.array(salinity_mushy, dtype=object)
output_dir = Path(output_dir) # ensure it's a Path
np.save(output_dir / "residuals.npy", residuals)
np.save(output_dir / "temperature_mushy.npy", temperature_mushy)
np.save(output_dir / "phi_mushy.npy", phi_mushy)
np.save(output_dir / "salinity_mushy.npy", salinity_mushy)
print("Residuals exported successfully.")