1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
//! Temperature simulator.
//!
//! ## Model
//!
//! Temperature simulation is based on the well-known analogy between electrical
//! and thermal circuits. Given a system with `units` processing elements, an
//! equivalent thermal RC circuit with `nodes` thermal nodes is constructed. The
//! circuit is then used for modeling the thermal behavior of the system.
//! Concretely, the thermal behavior is described using the following system of
//! differential-algebraic equations:
//!
//! ```math
//!     dT
//! Cth -- + Gth (T - Tamb) = Mp P
//!     dt
//!
//! Q = Mq T
//! ```
//!
//! where
//!
//! * `Cth` is a `nodes × nodes` diagonal matrix of the thermal capacitance;
//!
//! * `Gth` is a `nodes × nodes` symmetric, positive-definite matrix of the
//!   thermal conductance;
//!
//! * `T` is a `nodes`-element vector of the temperature of the thermal nodes;
//!
//! * `Tamb` is a `nodes`-element vector of the ambient temperature;
//!
//! * `P` is a `units`-element vector of the power dissipation of the processing
//!   elements;
//!
//! * `Mp` is a `nodes × units` matrix that distributes the power dissipation of
//!   the processing elements onto the thermal nodes;
//!
//! * `Q` is a `spots`-element vector of the temperature of interest; and
//!
//! * `Mq` is a `spots × nodes` matrix that aggregates the temperature of the
//!   thermal nodes into the temperature of interest.
//!
//! ## Solution
//!
//! The original system is transformed into the following:
//!
//! ```math
//! dS
//! -- = A S + B P
//! dt
//!
//! Q = C S + Mq Tamb
//! ```
//!
//! where
//!
//! ```math
//! S = D^(-1) (T - Tamb),
//! A = -D Gth D,
//! B = D Mp,
//! C = Mq D, and
//! D = Cth^(-1/2).
//! ```
//!
//! The eigendecomposition of `A`, which is real and symmetric, is
//!
//! ```math
//! A = U diag(Λ) U^T.
//! ```
//!
//! For a short time interval `[0, Δt]`, the solution is obtained using the
//! following equation:
//!
//! ```math
//! S(t) = E S(0) + F P(0)
//! ```
//!
//! where
//!
//! ```math
//! E = exp(A Δt) = U diag(exp(λi Δt)) U^T and
//! F = A^(-1) (exp(A Δt) - I) B = U diag((exp(λi Δt) - 1) / λi) U^T B.
//! ```
//!
//! The solution makes use of the assumption that `Δt`, referred to as the time
//! step, is short enough so that the power dissipation does not change much
//! within `[0, Δt]`. In order to compute the temperature profile corresponding
//! for the whole time span of interest, the time span is split into small
//! subintervals, and the above equation is successively applied to each of
//! them.

#[cfg(test)]
extern crate assert;
extern crate matrix;

use std::{default, error, fmt, result};
use matrix::format::{Compressed, Diagonal};

/// A thermal circuit.
#[derive(Clone, Debug)]
pub struct Circuit {
    /// The thermal-capacitance matrix.
    pub capacitance: Diagonal<f64>,
    /// The thermal-conductance matrix.
    pub conductance: Compressed<f64>,
    /// The power-distribution matrix.
    pub distribution: Compressed<f64>,
    /// The temperature-aggregation matrix.
    pub aggregation: Compressed<f64>,
}

/// A configuration of temperature simulation.
#[derive(Clone, Copy, Debug)]
pub struct Config {
    /// The temperature of the ambience in Kelvin.
    pub ambience: f64,
    /// The time step of the simulator in seconds.
    pub time_step: f64,
}

/// An error.
#[derive(Clone, Debug)]
pub struct Error(String);

/// A result.
pub type Result<T> = result::Result<T, Error>;

macro_rules! raise(
    ($message:expr) => (
        return Err(::Error($message.to_string()));
    );
);

macro_rules! ok(
    ($result:expr) => (
        match $result {
            Ok(result) => result,
            Err(error) => raise!(error),
        }
    );
);

impl fmt::Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(formatter)
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        &self.0
    }
}

impl default::Default for Config {
    #[inline]
    fn default() -> Config {
        Config {
            ambience: 318.15,
            time_step: 1e-3,
        }
    }
}

mod simulator;
pub mod circuit;

pub use simulator::Simulator;