Module pyangstrom.sample_solutions.kil_circular_room_temp

Expand source code
from typing import TypedDict

import numpy as np
import pandas as pd
from scipy.special import jv, yv

from pyangstrom.exp_setup import ExperimentalSetup
from pyangstrom.transform import Margins, Region
from pyangstrom.signal import fft_signal_processing, SignalProperties
from pyangstrom.fitting_methods.nelder_mead import NelderMeadEquations
from pyangstrom.fitting_methods.lsr import LsrEquations
from pyangstrom.helpers import calc_thermal_conductivity


class KilCircularRoomTempUnknowns(TypedDict):
    """The unknowns in Kil's 1D Solution for Cylindrical Coordinates."""
    thermal_diffusivity_m2__s: float
    convective_heat_transfer_coefficient_W__m2_K: float

class LogKilCircularRoomTempUnknowns(TypedDict):
    """The log variants of the unknowns in Kil's 1D Solution for Cylindrical
    Coordinates.
    """
    thermal_diffusivity_log10_m2__s: float
    convective_heat_transfer_coefficient_log10_W__m2_K: float

def J0(x):
    return jv(0, x)

def Y0(x):
    return yv(0, x)

class Solution(NelderMeadEquations, LsrEquations):
    """Implements equations for Kil's 1D Solution for Cylindrical Coordinates.
    """
    def __init__(
            self,
            margins: Margins,
            setup: ExperimentalSetup,
            sample_thickness_meters: float,
            heating_source_radius_meters: float,
            outer_boundary_radius_meters: float,
    ) -> None:
        """For more details, see
        https://github.com/RuralBrick/Angstrom-Method-Rewrite/wiki/Sample-Solutions#kils-1d-solution-for-cylindrical-coordinates
        """
        self.margins = margins
        self.time_seconds = self.append_dims(
            margins.seconds_elapsed,
            len(margins.displacements_meters.shape),
        )
        self.radii_meters = margins.displacements_meters
        self.sample_thickness_meters = sample_thickness_meters
        self.heating_source_radius_meters = heating_source_radius_meters
        self.outer_boundary_radius_meters = outer_boundary_radius_meters
        self.setup = setup
        self.angular_frequency_hertz = 2*np.pi*setup['heating_frequency_hertz']

    def append_dims(self, arr: np.ndarray, num_dims: int) -> np.ndarray:
        num_current_dims = len(arr.shape)
        expanded_arr = np.expand_dims(
            arr,
            axis=tuple(range(num_current_dims, num_current_dims + num_dims)),
        )
        return expanded_arr

    def calc_convective_heat_transfer_term(
            self,
            thermal_diffusivity_m2__s,
            convective_heat_transfer_coefficient_W__m2_K,
    ):
        h = convective_heat_transfer_coefficient_W__m2_K
        k = calc_thermal_conductivity(
            thermal_diffusivity_m2__s,
            self.setup['material_properties']['specific_heat_capacity_J__kg_K'],
            self.setup['material_properties']['density_kg__m3'],
        )
        d = self.sample_thickness_meters

        m2 = h / (k*d)

        return m2

    def calc_normalized_T1(
            self,
            thermal_diffusivity_m2__s,
            convective_heat_transfer_coefficient_W__m2_K,
    ):
        i = 1j
        r = self.radii_meters
        a = self.heating_source_radius_meters
        b = self.outer_boundary_radius_meters
        w = self.angular_frequency_hertz
        D = thermal_diffusivity_m2__s
        m2 = self.calc_convective_heat_transfer_term(
            thermal_diffusivity_m2__s,
            convective_heat_transfer_coefficient_W__m2_K,
        )

        X = i * np.sqrt(m2 + i*w/D)
        numerator = -Y0(-b*X) * J0(r*X) + J0(b*X) * Y0(-r*X)
        denominator = J0(b*X) * Y0(-a*X) - J0(a*X) * Y0(-b*X)
        T1 = 0.5 * numerator / denominator

        return T1

    def calc_normalized_T2(
            self,
            thermal_diffusivity_m2__s,
            convective_heat_transfer_coefficient_W__m2_K,
    ):
        i = 1j
        r = self.radii_meters
        a = self.heating_source_radius_meters
        b = self.outer_boundary_radius_meters
        w = self.angular_frequency_hertz
        D = thermal_diffusivity_m2__s
        m2 = self.calc_convective_heat_transfer_term(
            thermal_diffusivity_m2__s,
            convective_heat_transfer_coefficient_W__m2_K,
        )

        X = i * np.sqrt(m2 - i*w/D)
        numerator = -Y0(-b*X) * J0(r*X) + J0(b*X) * Y0(-r*X)
        denominator = J0(b*X) * Y0(-a*X) - J0(a*X) * Y0(-b*X)
        T2 = 0.5 * numerator / denominator

        return T2

    def calc_normalized_temps(
            self,
            thermal_diffusivity_m2__s,
            convective_heat_transfer_coefficient_W__m2_K,
    ):
        i = 1j
        t = self.time_seconds
        w = self.angular_frequency_hertz
        T1 = self.calc_normalized_T1(
            thermal_diffusivity_m2__s,
            convective_heat_transfer_coefficient_W__m2_K,
        )
        T2 = self.calc_normalized_T2(
            thermal_diffusivity_m2__s,
            convective_heat_transfer_coefficient_W__m2_K,
        )

        T = T1 * np.exp(i*w*t) + T2 * np.exp(-i*w*t)

        return T

    def unknowns_to_vector(
            self,
            unknowns: KilCircularRoomTempUnknowns,
    ) -> np.ndarray:
        vector = np.array([
            unknowns['thermal_diffusivity_m2__s'],
            unknowns['convective_heat_transfer_coefficient_W__m2_K'],
        ])
        return vector

    def vector_to_unknowns(
            self,
            vector: np.ndarray
    ) -> KilCircularRoomTempUnknowns:
        unknowns: KilCircularRoomTempUnknowns = {
            'thermal_diffusivity_m2__s': vector[0],
            'convective_heat_transfer_coefficient_W__m2_K': vector[1],
        }
        return unknowns

    def solve(self, unknowns: KilCircularRoomTempUnknowns) -> SignalProperties:
        timestamps = pd.DatetimeIndex(
            1e9 * self.margins.seconds_elapsed,
            dtype='datetime64[ns]',
        )
        temps = self.calc_normalized_temps(
            unknowns['thermal_diffusivity_m2__s'],
            unknowns['convective_heat_transfer_coefficient_W__m2_K'],
        )
        region = Region(timestamps, temps, self.margins)
        return fft_signal_processing(region, self.setup)

    def vector_solve(self, unknowns_vector: np.ndarray) -> SignalProperties:
        thermal_diffusivity_m2__s, convective_heat_transfer_coefficient_W__m2_K = unknowns_vector
        timestamps = pd.DatetimeIndex(
            1e9 * self.margins.seconds_elapsed,
            dtype='datetime64[ns]',
        )
        temps = self.calc_normalized_temps(
            thermal_diffusivity_m2__s,
            convective_heat_transfer_coefficient_W__m2_K,
        )
        region = Region(timestamps, temps, self.margins)
        return fft_signal_processing(region, self.setup)

class LogSolution(Solution):
    """Implements equations for the log variant of Kil's 1D Solution for
    Cylindrical Coordinates.
    """
    def unknowns_to_vector(
            self,
            unknowns: LogKilCircularRoomTempUnknowns,
    ) -> np.ndarray:
        vector = np.array([
            unknowns['thermal_diffusivity_log10_m2__s'],
            unknowns['convective_heat_transfer_coefficient_log10_W__m2_K']
        ])
        return vector

    def vector_to_unknowns(
            self,
            vector: np.ndarray,
    ) -> LogKilCircularRoomTempUnknowns:
        unknowns: LogKilCircularRoomTempUnknowns = {
            'thermal_diffusivity_log10_m2__s': vector[0],
            'convective_heat_transfer_coefficient_log10_W__m2_K': vector[1],
        }
        return unknowns

    def solve(self, unknowns: LogKilCircularRoomTempUnknowns) -> SignalProperties:
        unknowns_vector = np.power(10.0, self.unknowns_to_vector(unknowns))
        return super().vector_solve(unknowns_vector)

    def vector_solve(self, unknowns_vector: np.ndarray) -> SignalProperties:
        return super().vector_solve(np.power(10.0, unknowns_vector))

Functions

def J0(x)
Expand source code
def J0(x):
    return jv(0, x)
def Y0(x)
Expand source code
def Y0(x):
    return yv(0, x)

Classes

class KilCircularRoomTempUnknowns (*args, **kwargs)

The unknowns in Kil's 1D Solution for Cylindrical Coordinates.

Expand source code
class KilCircularRoomTempUnknowns(TypedDict):
    """The unknowns in Kil's 1D Solution for Cylindrical Coordinates."""
    thermal_diffusivity_m2__s: float
    convective_heat_transfer_coefficient_W__m2_K: float

Ancestors

  • builtins.dict

Class variables

var convective_heat_transfer_coefficient_W__m2_K : float
var thermal_diffusivity_m2__s : float
class LogKilCircularRoomTempUnknowns (*args, **kwargs)

The log variants of the unknowns in Kil's 1D Solution for Cylindrical Coordinates.

Expand source code
class LogKilCircularRoomTempUnknowns(TypedDict):
    """The log variants of the unknowns in Kil's 1D Solution for Cylindrical
    Coordinates.
    """
    thermal_diffusivity_log10_m2__s: float
    convective_heat_transfer_coefficient_log10_W__m2_K: float

Ancestors

  • builtins.dict

Class variables

var convective_heat_transfer_coefficient_log10_W__m2_K : float
var thermal_diffusivity_log10_m2__s : float
class LogSolution (margins: Margins, setup: ExperimentalSetup, sample_thickness_meters: float, heating_source_radius_meters: float, outer_boundary_radius_meters: float)

Implements equations for the log variant of Kil's 1D Solution for Cylindrical Coordinates.

For more details, see https://github.com/RuralBrick/Angstrom-Method-Rewrite/wiki/Sample-Solutions#kils-1d-solution-for-cylindrical-coordinates

Expand source code
class LogSolution(Solution):
    """Implements equations for the log variant of Kil's 1D Solution for
    Cylindrical Coordinates.
    """
    def unknowns_to_vector(
            self,
            unknowns: LogKilCircularRoomTempUnknowns,
    ) -> np.ndarray:
        vector = np.array([
            unknowns['thermal_diffusivity_log10_m2__s'],
            unknowns['convective_heat_transfer_coefficient_log10_W__m2_K']
        ])
        return vector

    def vector_to_unknowns(
            self,
            vector: np.ndarray,
    ) -> LogKilCircularRoomTempUnknowns:
        unknowns: LogKilCircularRoomTempUnknowns = {
            'thermal_diffusivity_log10_m2__s': vector[0],
            'convective_heat_transfer_coefficient_log10_W__m2_K': vector[1],
        }
        return unknowns

    def solve(self, unknowns: LogKilCircularRoomTempUnknowns) -> SignalProperties:
        unknowns_vector = np.power(10.0, self.unknowns_to_vector(unknowns))
        return super().vector_solve(unknowns_vector)

    def vector_solve(self, unknowns_vector: np.ndarray) -> SignalProperties:
        return super().vector_solve(np.power(10.0, unknowns_vector))

Ancestors

Inherited members

class Solution (margins: Margins, setup: ExperimentalSetup, sample_thickness_meters: float, heating_source_radius_meters: float, outer_boundary_radius_meters: float)

Implements equations for Kil's 1D Solution for Cylindrical Coordinates.

For more details, see https://github.com/RuralBrick/Angstrom-Method-Rewrite/wiki/Sample-Solutions#kils-1d-solution-for-cylindrical-coordinates

Expand source code
class Solution(NelderMeadEquations, LsrEquations):
    """Implements equations for Kil's 1D Solution for Cylindrical Coordinates.
    """
    def __init__(
            self,
            margins: Margins,
            setup: ExperimentalSetup,
            sample_thickness_meters: float,
            heating_source_radius_meters: float,
            outer_boundary_radius_meters: float,
    ) -> None:
        """For more details, see
        https://github.com/RuralBrick/Angstrom-Method-Rewrite/wiki/Sample-Solutions#kils-1d-solution-for-cylindrical-coordinates
        """
        self.margins = margins
        self.time_seconds = self.append_dims(
            margins.seconds_elapsed,
            len(margins.displacements_meters.shape),
        )
        self.radii_meters = margins.displacements_meters
        self.sample_thickness_meters = sample_thickness_meters
        self.heating_source_radius_meters = heating_source_radius_meters
        self.outer_boundary_radius_meters = outer_boundary_radius_meters
        self.setup = setup
        self.angular_frequency_hertz = 2*np.pi*setup['heating_frequency_hertz']

    def append_dims(self, arr: np.ndarray, num_dims: int) -> np.ndarray:
        num_current_dims = len(arr.shape)
        expanded_arr = np.expand_dims(
            arr,
            axis=tuple(range(num_current_dims, num_current_dims + num_dims)),
        )
        return expanded_arr

    def calc_convective_heat_transfer_term(
            self,
            thermal_diffusivity_m2__s,
            convective_heat_transfer_coefficient_W__m2_K,
    ):
        h = convective_heat_transfer_coefficient_W__m2_K
        k = calc_thermal_conductivity(
            thermal_diffusivity_m2__s,
            self.setup['material_properties']['specific_heat_capacity_J__kg_K'],
            self.setup['material_properties']['density_kg__m3'],
        )
        d = self.sample_thickness_meters

        m2 = h / (k*d)

        return m2

    def calc_normalized_T1(
            self,
            thermal_diffusivity_m2__s,
            convective_heat_transfer_coefficient_W__m2_K,
    ):
        i = 1j
        r = self.radii_meters
        a = self.heating_source_radius_meters
        b = self.outer_boundary_radius_meters
        w = self.angular_frequency_hertz
        D = thermal_diffusivity_m2__s
        m2 = self.calc_convective_heat_transfer_term(
            thermal_diffusivity_m2__s,
            convective_heat_transfer_coefficient_W__m2_K,
        )

        X = i * np.sqrt(m2 + i*w/D)
        numerator = -Y0(-b*X) * J0(r*X) + J0(b*X) * Y0(-r*X)
        denominator = J0(b*X) * Y0(-a*X) - J0(a*X) * Y0(-b*X)
        T1 = 0.5 * numerator / denominator

        return T1

    def calc_normalized_T2(
            self,
            thermal_diffusivity_m2__s,
            convective_heat_transfer_coefficient_W__m2_K,
    ):
        i = 1j
        r = self.radii_meters
        a = self.heating_source_radius_meters
        b = self.outer_boundary_radius_meters
        w = self.angular_frequency_hertz
        D = thermal_diffusivity_m2__s
        m2 = self.calc_convective_heat_transfer_term(
            thermal_diffusivity_m2__s,
            convective_heat_transfer_coefficient_W__m2_K,
        )

        X = i * np.sqrt(m2 - i*w/D)
        numerator = -Y0(-b*X) * J0(r*X) + J0(b*X) * Y0(-r*X)
        denominator = J0(b*X) * Y0(-a*X) - J0(a*X) * Y0(-b*X)
        T2 = 0.5 * numerator / denominator

        return T2

    def calc_normalized_temps(
            self,
            thermal_diffusivity_m2__s,
            convective_heat_transfer_coefficient_W__m2_K,
    ):
        i = 1j
        t = self.time_seconds
        w = self.angular_frequency_hertz
        T1 = self.calc_normalized_T1(
            thermal_diffusivity_m2__s,
            convective_heat_transfer_coefficient_W__m2_K,
        )
        T2 = self.calc_normalized_T2(
            thermal_diffusivity_m2__s,
            convective_heat_transfer_coefficient_W__m2_K,
        )

        T = T1 * np.exp(i*w*t) + T2 * np.exp(-i*w*t)

        return T

    def unknowns_to_vector(
            self,
            unknowns: KilCircularRoomTempUnknowns,
    ) -> np.ndarray:
        vector = np.array([
            unknowns['thermal_diffusivity_m2__s'],
            unknowns['convective_heat_transfer_coefficient_W__m2_K'],
        ])
        return vector

    def vector_to_unknowns(
            self,
            vector: np.ndarray
    ) -> KilCircularRoomTempUnknowns:
        unknowns: KilCircularRoomTempUnknowns = {
            'thermal_diffusivity_m2__s': vector[0],
            'convective_heat_transfer_coefficient_W__m2_K': vector[1],
        }
        return unknowns

    def solve(self, unknowns: KilCircularRoomTempUnknowns) -> SignalProperties:
        timestamps = pd.DatetimeIndex(
            1e9 * self.margins.seconds_elapsed,
            dtype='datetime64[ns]',
        )
        temps = self.calc_normalized_temps(
            unknowns['thermal_diffusivity_m2__s'],
            unknowns['convective_heat_transfer_coefficient_W__m2_K'],
        )
        region = Region(timestamps, temps, self.margins)
        return fft_signal_processing(region, self.setup)

    def vector_solve(self, unknowns_vector: np.ndarray) -> SignalProperties:
        thermal_diffusivity_m2__s, convective_heat_transfer_coefficient_W__m2_K = unknowns_vector
        timestamps = pd.DatetimeIndex(
            1e9 * self.margins.seconds_elapsed,
            dtype='datetime64[ns]',
        )
        temps = self.calc_normalized_temps(
            thermal_diffusivity_m2__s,
            convective_heat_transfer_coefficient_W__m2_K,
        )
        region = Region(timestamps, temps, self.margins)
        return fft_signal_processing(region, self.setup)

Ancestors

Subclasses

Methods

def append_dims(self, arr: numpy.ndarray, num_dims: int) ‑> numpy.ndarray
Expand source code
def append_dims(self, arr: np.ndarray, num_dims: int) -> np.ndarray:
    num_current_dims = len(arr.shape)
    expanded_arr = np.expand_dims(
        arr,
        axis=tuple(range(num_current_dims, num_current_dims + num_dims)),
    )
    return expanded_arr
def calc_convective_heat_transfer_term(self, thermal_diffusivity_m2__s, convective_heat_transfer_coefficient_W__m2_K)
Expand source code
def calc_convective_heat_transfer_term(
        self,
        thermal_diffusivity_m2__s,
        convective_heat_transfer_coefficient_W__m2_K,
):
    h = convective_heat_transfer_coefficient_W__m2_K
    k = calc_thermal_conductivity(
        thermal_diffusivity_m2__s,
        self.setup['material_properties']['specific_heat_capacity_J__kg_K'],
        self.setup['material_properties']['density_kg__m3'],
    )
    d = self.sample_thickness_meters

    m2 = h / (k*d)

    return m2
def calc_normalized_T1(self, thermal_diffusivity_m2__s, convective_heat_transfer_coefficient_W__m2_K)
Expand source code
def calc_normalized_T1(
        self,
        thermal_diffusivity_m2__s,
        convective_heat_transfer_coefficient_W__m2_K,
):
    i = 1j
    r = self.radii_meters
    a = self.heating_source_radius_meters
    b = self.outer_boundary_radius_meters
    w = self.angular_frequency_hertz
    D = thermal_diffusivity_m2__s
    m2 = self.calc_convective_heat_transfer_term(
        thermal_diffusivity_m2__s,
        convective_heat_transfer_coefficient_W__m2_K,
    )

    X = i * np.sqrt(m2 + i*w/D)
    numerator = -Y0(-b*X) * J0(r*X) + J0(b*X) * Y0(-r*X)
    denominator = J0(b*X) * Y0(-a*X) - J0(a*X) * Y0(-b*X)
    T1 = 0.5 * numerator / denominator

    return T1
def calc_normalized_T2(self, thermal_diffusivity_m2__s, convective_heat_transfer_coefficient_W__m2_K)
Expand source code
def calc_normalized_T2(
        self,
        thermal_diffusivity_m2__s,
        convective_heat_transfer_coefficient_W__m2_K,
):
    i = 1j
    r = self.radii_meters
    a = self.heating_source_radius_meters
    b = self.outer_boundary_radius_meters
    w = self.angular_frequency_hertz
    D = thermal_diffusivity_m2__s
    m2 = self.calc_convective_heat_transfer_term(
        thermal_diffusivity_m2__s,
        convective_heat_transfer_coefficient_W__m2_K,
    )

    X = i * np.sqrt(m2 - i*w/D)
    numerator = -Y0(-b*X) * J0(r*X) + J0(b*X) * Y0(-r*X)
    denominator = J0(b*X) * Y0(-a*X) - J0(a*X) * Y0(-b*X)
    T2 = 0.5 * numerator / denominator

    return T2
def calc_normalized_temps(self, thermal_diffusivity_m2__s, convective_heat_transfer_coefficient_W__m2_K)
Expand source code
def calc_normalized_temps(
        self,
        thermal_diffusivity_m2__s,
        convective_heat_transfer_coefficient_W__m2_K,
):
    i = 1j
    t = self.time_seconds
    w = self.angular_frequency_hertz
    T1 = self.calc_normalized_T1(
        thermal_diffusivity_m2__s,
        convective_heat_transfer_coefficient_W__m2_K,
    )
    T2 = self.calc_normalized_T2(
        thermal_diffusivity_m2__s,
        convective_heat_transfer_coefficient_W__m2_K,
    )

    T = T1 * np.exp(i*w*t) + T2 * np.exp(-i*w*t)

    return T

Inherited members