Skip to content
Snippets Groups Projects
Commit 16d2038c authored by Rahil Doshi's avatar Rahil Doshi
Browse files

Merge branch 'release/v0.1.0'

parents bc161d55 2e0fc605
Branches
Tags
No related merge requests found
Pipeline #76706 passed
import re
import numpy as np
from pystencils.types import PsCustomType
from pystencilssfg import SfgComposer
......@@ -53,30 +54,45 @@ class InterpolationArrayContainer(CustomGenerator):
corresponding to temperature_array.
Raises:
ValueError: If arrays are empty, have different lengths, or are not monotonic.
TypeError: If name is not a string or arrays are not numpy arrays.
"""
super().__init__()
# Validate inputs
if not isinstance(name, str) or not name:
raise TypeError("Name must be a non-empty string")
if not re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*$', name):
raise ValueError(f"'{name}' is not a valid C++ class name")
if not isinstance(temperature_array, np.ndarray) or not isinstance(energy_density_array, np.ndarray):
raise TypeError("Temperature and energy arrays must be numpy arrays")
self.name = name
self.T_array = temperature_array
self.E_array = energy_density_array
# Prepare arrays and determine best method
self.data = prepare_interpolation_arrays(self.T_array, self.E_array)
self.method = self.data["method"]
# Store arrays for binary search (always available)
self.T_bs = self.data["T_bs"]
self.E_bs = self.data["E_bs"]
# Store arrays for double lookup if available
if self.method == "double_lookup":
self.T_eq = self.data["T_eq"]
self.E_neq = self.data["E_neq"]
self.E_eq = self.data["E_eq"]
self.inv_delta_E_eq = self.data["inv_delta_E_eq"]
self.idx_map = self.data["idx_map"]
self.has_double_lookup = True
else:
self.has_double_lookup = False
try:
self.data = prepare_interpolation_arrays(T_array=self.T_array, E_array=self.E_array, verbose=False)
self.method = self.data["method"]
# Store arrays for binary search (always available)
self.T_bs = self.data["T_bs"]
self.E_bs = self.data["E_bs"]
# Store arrays for double lookup if available
if self.method == "double_lookup":
self.T_eq = self.data["T_eq"]
self.E_neq = self.data["E_neq"]
self.E_eq = self.data["E_eq"]
self.inv_delta_E_eq = self.data["inv_delta_E_eq"]
self.idx_map = self.data["idx_map"]
self.has_double_lookup = True
else:
self.has_double_lookup = False
except Exception as e:
raise ValueError(f"Failed to prepare interpolation arrays: {e}") from e
@classmethod
def from_material(cls, name: str, material):
......
......@@ -297,10 +297,23 @@ def create_idx_mapping(E_neq: np.ndarray, E_eq: np.ndarray) -> np.ndarray:
return idx_map.astype(np.int32)
def prepare_interpolation_arrays(T_array: np.ndarray, E_array: np.ndarray) -> dict:
def prepare_interpolation_arrays(T_array: np.ndarray, E_array: np.ndarray, verbose=False) -> dict:
"""
Validates input arrays and prepares data for interpolation.
Returns a dictionary with arrays and metadata for the appropriate method.
Args:
T_array: Array of temperature values
E_array: Array of energy density values corresponding to temperatures
verbose: If True, prints diagnostic information during processing
Returns:
A dictionary with arrays and metadata for the appropriate interpolation method:
- Common keys: 'T_bs', 'E_bs', 'method', 'is_equidistant', 'increment'
- Additional keys for double_lookup method: 'T_eq', 'E_neq', 'E_eq',
'inv_delta_E_eq', 'idx_map'
Raises:
ValueError: If arrays don't meet requirements for interpolation
"""
# Convert to numpy arrays if not already
T_array = np.asarray(T_array)
......@@ -338,43 +351,59 @@ def prepare_interpolation_arrays(T_array: np.ndarray, E_array: np.ndarray) -> di
# Flip arrays if temperature is in descending order
if T_decreasing:
# print("Temperature array is descending, flipping arrays for processing")
if verbose:
print("Temperature array is descending, flipping arrays for processing")
T_bs = np.flip(T_bs)
E_bs = np.flip(E_bs)
# Check for strictly increasing values
has_warnings = False
try:
check_strictly_increasing(T_bs, "Temperature array")
check_strictly_increasing(E_bs, "Energy density array")
except ValueError as e:
print(f"Warning: {e}")
print("Continuing with interpolation, but results may be less accurate")
has_warnings = True
if verbose:
print(f"Warning: {e}")
print("Continuing with interpolation, but results may be less accurate")
# Use your existing check_equidistant function to determine if suitable for double lookup
# Use the existing check_equidistant function to determine if suitable for double lookup
T_incr = check_equidistant(T_bs)
is_equidistant = T_incr != 0.0
# Initialize result with common fields
result = {
"T_bs": T_bs,
"E_bs": E_bs,
"method": "binary_search"
"method": "binary_search",
"is_equidistant": is_equidistant,
"increment": T_incr if is_equidistant else 0.0,
"has_warnings": has_warnings
}
# If temperature is equidistant, prepare for double lookup
if is_equidistant:
# print(f"Temperature array is equidistant with increment {T_incr}, using double lookup")
# Create equidistant energy array and mapping
E_eq, inv_delta_E_eq = E_eq_from_E_neq(E_bs)
idx_mapping = create_idx_mapping(E_bs, E_eq)
result.update({
"T_eq": T_bs,
"E_neq": E_bs,
"E_eq": E_eq,
"inv_delta_E_eq": inv_delta_E_eq,
"idx_map": idx_mapping,
"method": "double_lookup"
})
else:
if verbose:
print(f"Temperature array is equidistant with increment {T_incr}, using double lookup")
try:
# Create equidistant energy array and mapping
E_eq, inv_delta_E_eq = E_eq_from_E_neq(E_bs)
idx_mapping = create_idx_mapping(E_bs, E_eq)
result.update({
"T_eq": T_bs,
"E_neq": E_bs,
"E_eq": E_eq,
"inv_delta_E_eq": inv_delta_E_eq,
"idx_map": idx_mapping,
"method": "double_lookup"
})
except Exception as e:
if verbose:
print(f"Warning: Failed to create double lookup tables: {e}")
print("Falling back to binary search method")
elif verbose:
print("Temperature array is not equidistant, using binary search")
return result
......
......@@ -8,7 +8,6 @@ NumericType = TypeVar('NumericType', float, np.float32, np.float64)
# Constants
ABSOLUTE_ZERO = 0.0 # Kelvin
DEFAULT_TOLERANCE = 1e-10
def sympy_wrapper(value: Union[sp.Expr, NumericType, ArrayTypes, MaterialProperty]) \
......@@ -27,8 +26,6 @@ def sympy_wrapper(value: Union[sp.Expr, NumericType, ArrayTypes, MaterialPropert
if isinstance(value, sp.Expr):
return sp.simplify(value)
if isinstance(value, (float, np.int32, np.int64, np.float32, np.float64)): # np.floating
# if abs(value) < DEFAULT_TOLERANCE:
# return sp.Float(0.0)
return sp.Float(float(value))
if isinstance(value, ArrayTypes): # Handles lists, tuples, and arrays
try:
......@@ -51,26 +48,6 @@ def material_property_wrapper(value: Union[sp.Expr, NumericType, ArrayTypes]) \
return MaterialProperty(wrapped_value)
def _validate_positive(*values, names=None):
"""Validate that float values are positive."""
if names is None:
names = [f"Value {i+1}" for i in range(len(values))]
for value, name in zip(values, names):
if isinstance(value, float) and value <= 0:
raise ValueError(f"{name} must be positive, got {value}")
def _validate_non_negative(*values, names=None):
"""Validate that float values are non-negative."""
if names is None:
names = [f"Value {i+1}" for i in range(len(values))]
for value, name in zip(values, names):
if isinstance(value, float) and value < 0:
raise ValueError(f"{name} cannot be negative, got {value}")
def _prepare_material_expressions(*properties):
"""Prepare expressions and collect assignments from material properties."""
sub_assignments = []
......@@ -82,7 +59,6 @@ def _prepare_material_expressions(*properties):
expressions.append(prop.expr)
else:
expressions.append(sympy_wrapper(prop))
return expressions, sub_assignments
......@@ -111,13 +87,6 @@ def density_by_thermal_expansion(
raise ValueError(f"Temperature cannot be below absolute zero ({ABSOLUTE_ZERO}K)")
if isinstance(temperature, ArrayTypes):
raise TypeError(f"Incompatible input type for temperature. Expected float or sp.Expr, got {type(temperature)}")
if temperature_base < ABSOLUTE_ZERO:
raise ValueError(f"Base temperature cannot be below absolute zero ({ABSOLUTE_ZERO}K)")
if density_base <= 0:
raise ValueError("Base density must be positive")
if isinstance(thermal_expansion_coefficient, float) and (thermal_expansion_coefficient < -3e-5 or thermal_expansion_coefficient > 0.001):
raise ValueError(f"Thermal expansion coefficient must be between -3e-5 and 0.001, got {thermal_expansion_coefficient}")
try:
tec_expr = thermal_expansion_coefficient.expr if isinstance(thermal_expansion_coefficient, MaterialProperty) else sympy_wrapper(thermal_expansion_coefficient)
sub_assignments = thermal_expansion_coefficient.assignments if isinstance(thermal_expansion_coefficient, MaterialProperty) else []
......@@ -145,11 +114,8 @@ def thermal_diffusivity_by_heat_conductivity(
TypeError: If incompatible input data types are provided.
ValueError: If physically impossible values are used.
"""
_validate_positive(heat_conductivity, density, heat_capacity, names=["Heat conductivity", "Density", "Heat capacity"])
(k_expr, rho_expr, cp_expr), sub_assignments \
= _prepare_material_expressions(heat_conductivity, density, heat_capacity)
try:
thermal_diffusivity = k_expr / (rho_expr * cp_expr)
return MaterialProperty(thermal_diffusivity, sub_assignments)
......@@ -164,14 +130,6 @@ def energy_density_standard(
latent_heat: Union[float, MaterialProperty]) \
-> MaterialProperty:
# Input validation to check for incompatible data types
if isinstance(temperature, float) and temperature < ABSOLUTE_ZERO:
raise ValueError(f"Temperature cannot be below absolute zero ({ABSOLUTE_ZERO}K)")
_validate_positive(density, heat_capacity, names=['Density', 'Heat capacity'])
_validate_non_negative(latent_heat, names=['Latent heat'])
(density_expr, heat_capacity_expr, latent_heat_expr), sub_assignments \
= _prepare_material_expressions(density, heat_capacity, latent_heat)
......@@ -193,9 +151,6 @@ def energy_density_enthalpy_based(
latent_heat: Union[float, MaterialProperty]) \
-> MaterialProperty:
_validate_positive(density, specific_enthalpy, names=["Density", "Specific enthalpy"])
_validate_non_negative(latent_heat, names=["Latent heat"])
(density_expr, specific_enthalpy_expr, latent_heat_expr), sub_assignments \
= _prepare_material_expressions(density, specific_enthalpy, latent_heat)
......@@ -208,8 +163,6 @@ def energy_density_total_enthalpy(
specific_enthalpy: Union[float, MaterialProperty]) \
-> MaterialProperty:
_validate_positive(density, specific_enthalpy, names=["Density", "Specific enthalpy"])
(density_expr, specific_enthalpy_expr), sub_assignments \
= _prepare_material_expressions(density, specific_enthalpy)
......
......@@ -153,40 +153,6 @@ class MaterialConfigParser:
if missing_fields:
raise ValueError(f"Missing required fields: {', '.join(missing_fields)}")
@staticmethod
def _validate_property_values(properties: Dict[str, Any]) -> None:
"""
Validate property values for type and range constraints.
Args:
properties (Dict[str, Any]): Dictionary of properties to validate.
Raises:
ValueError: If any property value is invalid.
"""
for prop_name, prop_value in properties.items():
BASE_PROPERTIES = {'base_temperature', 'base_density'}
POSITIVE_PROPERTIES = {'density', 'heat_capacity', 'heat_conductivity', 'specific_enthalpy'}
NON_NEGATIVE_PROPERTIES = {'latent_heat'}
if prop_value is None or (isinstance(prop_value, str) and prop_value.strip() == ''):
raise ValueError(f"Property '{prop_name}' has an empty or undefined value")
if prop_name in BASE_PROPERTIES:
if not isinstance(prop_value, float) or prop_value <= 0:
raise ValueError(f"'{prop_name}' must be a positive number of type float, "
f"got {prop_value} of type {type(prop_value).__name__}")
if prop_name in POSITIVE_PROPERTIES:
if isinstance(prop_value, float) and prop_value <= 0:
raise ValueError(f"'{prop_name}' must be positive, got {prop_value}")
if prop_name in NON_NEGATIVE_PROPERTIES:
if isinstance(prop_value, float) and prop_value < 0:
raise ValueError(f"'{prop_name}' cannot be negative, got {prop_value}")
if prop_name == 'thermal_expansion_coefficient':
if isinstance(prop_value, float) and (prop_value < -3e-5 or prop_value > 0.001):
raise ValueError(f"'{prop_name}' value {prop_value} is outside the expected range (-3e-5/K to 0.001/K)")
if prop_name == 'energy_density_temperature_array':
if not (isinstance(prop_value, str) and prop_value.startswith('(') and prop_value.endswith(')')):
raise ValueError(f"'{prop_name}' must be a tuple of three comma-separated values representing (start, end, points/step)")
if prop_name in ['energy_density_solidus', 'energy_density_liquidus']:
raise ValueError(f"{prop_name} cannot be set directly. It is computed from other properties")
@staticmethod
def _validate_property_value(prop: str, value: Union[float, np.ndarray]) -> None:
"""
......@@ -210,20 +176,26 @@ class MaterialConfigParser:
# Property-specific range constraints
PROPERTY_RANGES = {
'base_temperature': (0, 5000), # K
'temperature': (0, 5000), # K
'base_density': (800, 22000), # kg/m³
'density': (800, 22000), # kg/m³
'base_density': (-100, 22000), # kg/m³
'density': (100, 22000), # kg/m³
'dynamic_viscosity': (1e-4, 1e5), # Pa·s
'energy_density': (0, 1e8), # J/m³
'energy_density_solidus': (0, 1e8), # J/m³
'energy_density_liquidus': (0, 1e8), # J/m³
'energy_density_temperature_array': (0, 5000), # K
'energy_density_array': (0, 1e8), # J/m³
'heat_capacity': (100, 10000), # J/(kg·K)
'heat_conductivity': (1, 600), # W/(m·K)
'thermal_expansion_coefficient': (-5e-5, 3e-5), # 1/K
'dynamic_viscosity': (1e-4, 1e5), # Pa·s
'kinematic_viscosity': (1e-8, 1e-3), # m²/s
'thermal_diffusivity': (1e-8, 1e-3), # m²/s
'surface_tension': (0.1, 3.0), # N/m
'latent_heat_of_fusion': (0, 600000), # J/kg
'latent_heat_of_vaporization': (50000, 12000000), # J/kg
'specific_enthalpy': (0, 15000000), # J/kg
'surface_tension': (0.1, 3.0), # N/m
'temperature': (0, 5000), # K
'temperature_array': (0, 5000), # K
'thermal_diffusivity': (1e-8, 1e-3), # m²/s
'thermal_expansion_coefficient': (-3e-5, 3e-5), # 1/K
}
try:
# Handle arrays (from file or key-val properties)
if isinstance(value, np.ndarray):
......@@ -232,7 +204,6 @@ class MaterialConfigParser:
raise ValueError(f"Property '{prop}' contains NaN values.")
if np.isinf(value).any():
raise ValueError(f"Property '{prop}' contains infinite values.")
# Property-specific validations for arrays
if prop in POSITIVE_PROPERTIES:
if (value <= 0).any():
......@@ -240,14 +211,12 @@ class MaterialConfigParser:
bad_values = value[value <= 0]
raise ValueError(f"All '{prop}' values must be positive. Found {len(bad_indices)} invalid values "
f"at indices {bad_indices}: {bad_values}.")
if prop in NON_NEGATIVE_PROPERTIES or prop in ARRAY_PROPERTIES:
if (value < 0).any():
bad_indices = np.where(value < 0)[0]
bad_values = value[value < 0]
raise ValueError(f"All '{prop}' values must be non-negative. Found {len(bad_indices)} invalid values "
f"at indices {bad_indices}: {bad_values}.")
# Check range constraints if applicable
if prop in PROPERTY_RANGES:
min_val, max_val = PROPERTY_RANGES[prop]
......@@ -256,35 +225,29 @@ class MaterialConfigParser:
out_values = value[out_of_range]
raise ValueError(f"'{prop}' contains values outside expected range ({min_val} to {max_val}) "
f"\n -> Found {len(out_of_range)} out-of-range values at indices {out_of_range}: {out_values}")
# Handle single values (from constant or computed properties)
# Handle single values (from constant properties)
else:
# Check for NaN or infinite values
if np.isnan(value):
raise ValueError(f"Property '{prop}' is NaN.")
if np.isinf(value):
raise ValueError(f"Property '{prop}' is infinite.")
# Type checking
if not isinstance(value, float):
raise TypeError(f"Property '{prop}' must be a float, got {type(value).__name__}. "
f"\n -> Please use decimal notation (e.g., 1.0 instead of 1) or scientific notation.")
# Property-specific validations for single values
if prop in BASE_PROPERTIES or prop in POSITIVE_PROPERTIES:
if value <= 0:
raise ValueError(f"Property '{prop}' must be positive, got {value}.")
if prop in NON_NEGATIVE_PROPERTIES:
if value < 0:
raise ValueError(f"Property '{prop}' must be non-negative, got {value}.")
# Check range constraints if applicable
if prop in PROPERTY_RANGES:
min_val, max_val = PROPERTY_RANGES[prop]
if value < min_val or value > max_val:
raise ValueError(f"Property '{prop}' value {value} is outside expected range ({min_val} to {max_val}).")
except Exception as e:
raise ValueError(f"Failed to validate property value \n -> {e}")
......
......@@ -9,12 +9,12 @@ class Constants:
Attributes:
temperature_room (float): Room temperature in Kelvin.
N_a (float): Avogadro's number, the number of constituent particles (usually atoms or molecules) in one mole of a given substance.
u (float): Atomic mass unit in kilograms.
amu (float): Atomic mass unit in kilograms.
e (float): Elementary charge, the electric charge carried by a single proton or the magnitude of the electric charge carried by a single electron.
speed_of_light (float): Speed of light in vacuum in meters per second.
"""
temperature_room: float = 298.15 # Room temperature in Kelvin
N_a: float = 6.022141e23 # Avogadro's number, /mol
u: float = 1.660538e-27 # Atomic mass unit, kg
amu: float = 1.660538e-27 # Atomic mass unit, kg
e: float = 1.60217657e-19 # Elementary charge, C
speed_of_light: float = 0.299792458e9 # Speed of light, m/s
......@@ -8,7 +8,7 @@ from pymatlib.core.elements import ChemicalElement
C = ChemicalElement(
name="Carbon",
atomic_number=6,
atomic_mass=12.0107 * Constants.u,
atomic_mass=12.0107 * Constants.amu,
temperature_melt=3915, # Melting temperature = 3915 K
temperature_boil=4300, # Boiling temperature = 4300 K
latent_heat_of_fusion=117000, # Latent heat of fusion = 117 kJ/mol
......@@ -18,7 +18,7 @@ C = ChemicalElement(
N = ChemicalElement(
name="Nitrogen",
atomic_number=7,
atomic_mass=14.0067 * Constants.u,
atomic_mass=14.0067 * Constants.amu,
temperature_melt=63.15, # Melting temperature = 63.15 K
temperature_boil=77.36, # Boiling temperature = 77.36 K
latent_heat_of_fusion=720, # Latent heat of fusion = 0.72 kJ/mol
......@@ -28,7 +28,7 @@ N = ChemicalElement(
Al = ChemicalElement(
name="Aluminium",
atomic_number=13, # Atomic number = 13 / Source: Periodic Table
atomic_mass=26.9815384 * Constants.u, # Atomic mass = 26.9815384 u / Source: NIST
atomic_mass=26.9815384 * Constants.amu, # Atomic mass = 26.9815384 amu / Source: NIST
temperature_melt=933.35, # Melting temperature = 933.35 K / Source: RSC
temperature_boil=2743, # Boiling temperature = 2743 K / Source: RSC
latent_heat_of_fusion=10700, # Latent heat of fusion = 10700 J/kg / Source: CRC
......@@ -38,7 +38,7 @@ Al = ChemicalElement(
Si = ChemicalElement(
name="Silicon",
atomic_number=14,
atomic_mass=28.0855 * Constants.u,
atomic_mass=28.0855 * Constants.amu,
temperature_melt=1687, # Melting temperature = 1687 K
temperature_boil=3538, # Boiling temperature = 3538 K
latent_heat_of_fusion=50200, # Latent heat of fusion = 50.2 kJ/mol
......@@ -48,7 +48,7 @@ Si = ChemicalElement(
P = ChemicalElement(
name="Phosphorus",
atomic_number=15,
atomic_mass=30.973762 * Constants.u,
atomic_mass=30.973762 * Constants.amu,
temperature_melt=317.3, # Melting temperature = 317.3 K
temperature_boil=553.7, # Boiling temperature = 553.7 K
latent_heat_of_fusion=2510, # Latent heat of fusion = 2.51 kJ/mol
......@@ -58,7 +58,7 @@ P = ChemicalElement(
S = ChemicalElement(
name="Sulfur",
atomic_number=16,
atomic_mass=32.065 * Constants.u,
atomic_mass=32.065 * Constants.amu,
temperature_melt=388.36, # Melting temperature = 388.36 K
temperature_boil=717.8, # Boiling temperature = 717.8 K
latent_heat_of_fusion=1730, # Latent heat of fusion = 1.73 kJ/mol
......@@ -68,7 +68,7 @@ S = ChemicalElement(
Ti = ChemicalElement(
name="Titanium",
atomic_number=22, # Atomic number = 22 / Source: Periodic Table
atomic_mass=47.867 * Constants.u, # Atomic mass = 47.867 u / Source: NIST
atomic_mass=47.867 * Constants.amu, # Atomic mass = 47.867 amu / Source: NIST
temperature_melt=1941, # Melting temperature = 1941 K / Source: RSC
temperature_boil=3560, # Boiling temperature = 3560 K / Source: RSC
latent_heat_of_fusion=18700, # Latent heat of fusion = 18700 J/kg / Source: CRC
......@@ -78,7 +78,7 @@ Ti = ChemicalElement(
V = ChemicalElement(
name="Vanadium",
atomic_number=23, # Atomic number = 23 / Source: Periodic Table
atomic_mass=50.9415 * Constants.u, # Atomic mass = 50.9415 u / Source: NIST
atomic_mass=50.9415 * Constants.amu, # Atomic mass = 50.9415 amu / Source: NIST
temperature_melt=2183, # Melting temperature = 2183 K / Source: RSC
temperature_boil=3680, # Boiling temperature = 3680 K / Source: RSC
latent_heat_of_fusion=21500, # Latent heat of fusion = 21500 J/kg / Source: CRC
......@@ -88,7 +88,7 @@ V = ChemicalElement(
Cr = ChemicalElement(
name="Chromium",
atomic_number=24, # Atomic number = 24 / Source: Periodic Table
atomic_mass=51.9961 * Constants.u, # Atomic mass = 51.9961 u / Source: NIST
atomic_mass=51.9961 * Constants.amu, # Atomic mass = 51.9961 amu / Source: NIST
temperature_melt=2180, # Melting temperature = 2180 K / Source: RSC
temperature_boil=2944, # Boiling temperature = 2944 K / Source: RSC
latent_heat_of_fusion=16500, # Latent heat of fusion = 16500 J/kg / Source: CRC
......@@ -98,7 +98,7 @@ Cr = ChemicalElement(
Mn = ChemicalElement(
name="Manganese",
atomic_number=25, # Atomic number = 25 / Source: Periodic Table
atomic_mass=54.938045 * Constants.u, # Atomic mass = 54.938045 u / Source: NIST
atomic_mass=54.938045 * Constants.amu, # Atomic mass = 54.938045 amu / Source: NIST
temperature_melt=1519, # Melting temperature = 1519 K / Source: RSC
temperature_boil=2334, # Boiling temperature = 2334 K / Source: RSC
latent_heat_of_fusion=12500, # Latent heat of fusion = 12500 J/kg / Source: CRC
......@@ -108,7 +108,7 @@ Mn = ChemicalElement(
Fe = ChemicalElement(
name="Iron",
atomic_number=26, # Atomic number = 26 / Source: Periodic Table
atomic_mass=55.845 * Constants.u, # Atomic mass = 55.845 u / Source: NIST
atomic_mass=55.845 * Constants.amu, # Atomic mass = 55.845 amu / Source: NIST
temperature_melt=1809, # Melting temperature = 1809 K / Source: RSC
temperature_boil=3134, # Boiling temperature = 3134 K / Source: RSC
latent_heat_of_fusion=13800, # Latent heat of fusion = 13800 J/kg / Source: CRC
......@@ -118,7 +118,7 @@ Fe = ChemicalElement(
Ni = ChemicalElement(
name="Nickel",
atomic_number=28, # Atomic number = 28 / Source: Periodic Table
atomic_mass=58.6934 * Constants.u, # Atomic mass = 58.6934 u / Source: NIST
atomic_mass=58.6934 * Constants.amu, # Atomic mass = 58.6934 amu / Source: NIST
temperature_melt=1728, # Melting temperature = 1728 K / Source: RSC
temperature_boil=3186, # Boiling temperature = 3186 K / Source: RSC
latent_heat_of_fusion=17200, # Latent heat of fusion = 17200 J/kg / Source: CRC
......@@ -128,7 +128,7 @@ Ni = ChemicalElement(
Mo = ChemicalElement(
name="Molybdenum",
atomic_number=42,
atomic_mass=95.96 * Constants.u,
atomic_mass=95.96 * Constants.amu,
temperature_melt=2896, # Melting temperature = 2896K (2623°C)
temperature_boil=4912, # Boiling temperature = 4912K (4639°C)
latent_heat_of_fusion=37480, # Latent heat of fusion = 37.48 kJ/mol
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment