Skip to content

Solver1T

Solver1T

Solver1T(
    dic: Optional[dict[str, Any]] = None,
    joule: Type[PowerTerm] = PowerTerm,
    solar: Type[PowerTerm] = PowerTerm,
    convective: Type[PowerTerm] = PowerTerm,
    radiative: Type[PowerTerm] = PowerTerm,
    precipitation: Type[PowerTerm] = PowerTerm,
)

Bases: Solver

Parameters:

Name Type Description Default

dic

dict[str, Any] | None

Input values used in power terms. If there is a missing value, a default is used.

None

joule

Type[PowerTerm]

Joule heating term class.

PowerTerm

solar

Type[PowerTerm]

Solar heating term class.

PowerTerm

convective

Type[PowerTerm]

Convective cooling term class.

PowerTerm

radiative

Type[PowerTerm]

Radiative cooling term class.

PowerTerm

precipitation

Type[PowerTerm]

Precipitation cooling term class.

PowerTerm

Returns:

Type Description
None

None

Source code in src/thermohl/solver/solver.py
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
def __init__(
    self,
    dic: Optional[dict[str, Any]] = None,
    joule: Type[PowerTerm] = PowerTerm,
    solar: Type[PowerTerm] = PowerTerm,
    convective: Type[PowerTerm] = PowerTerm,
    radiative: Type[PowerTerm] = PowerTerm,
    precipitation: Type[PowerTerm] = PowerTerm,
) -> None:
    """Create a Solver object.

    Args:
        dic (dict[str, Any] | None): Input values used in power terms. If there is a missing value, a default is used.
        joule (Type[PowerTerm]): Joule heating term class.
        solar (Type[PowerTerm]): Solar heating term class.
        convective (Type[PowerTerm]): Convective cooling term class.
        radiative (Type[PowerTerm]): Radiative cooling term class.
        precipitation (Type[PowerTerm]): Precipitation cooling term class.

    Returns:
        None

    """
    self.args = Parameters(dic)
    self.args.extend()
    self.joule_heating = joule(**self.args.__dict__)
    self.solar_heating = solar(**self.args.__dict__)
    self.convective_cooling = convective(**self.args.__dict__)
    self.radiative_cooling = radiative(**self.args.__dict__)
    self.precipitation_cooling = precipitation(**self.args.__dict__)
    self.args.compress()

steady_intensity

steady_intensity(
    max_conductor_temperature: floatArrayLike = np.array(
        []
    ),
    Imin: float = default.imin,
    Imax: float = default.imax,
    tol: float = default.tol,
    maxiter: int = default.maxiter,
    return_err: bool = False,
    return_power: bool = True,
) -> dict[str, np.ndarray]

Compute steady-state max intensity.

Compute the maximum intensity that can be run in a conductor without exceeding the temperature given in argument.

Parameters:

Name Type Description Default

max_conductor_temperature

float | ndarray

Maximum temperature.

array([])

Imin

float

Lower bound for intensity. The default is 0.

imin

Imax

float

Upper bound for intensity. The default is 9999.

imax

tol

float

Tolerance for temperature error. The default is 1.0E-06.

tol

maxiter

int

Max number of iterations. The default is 64.

maxiter

return_err

bool

Return final error on intensity to check convergence. The default is False.

False

return_power

bool

Return power term values. The default is True.

True

Returns:

Type Description
dict[str, ndarray]

dict[str, np.ndarray]: A dictionary with maximum intensity and other results (depending on inputs) in the keys,

dict[str, ndarray]

along with input data.

Source code in src/thermohl/solver/slv1t.py
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
def steady_intensity(
    self,
    max_conductor_temperature: floatArrayLike = np.array([]),
    Imin: float = default.imin,
    Imax: float = default.imax,
    tol: float = default.tol,
    maxiter: int = default.maxiter,
    return_err: bool = False,
    return_power: bool = True,
) -> dict[str, np.ndarray]:
    """Compute steady-state max intensity.

    Compute the maximum intensity that can be run in a conductor without
    exceeding the temperature given in argument.

    Args:
        max_conductor_temperature (float | numpy.ndarray): Maximum temperature.
        Imin (float, optional): Lower bound for intensity. The default is 0.
        Imax (float, optional): Upper bound for intensity. The default is 9999.
        tol (float, optional): Tolerance for temperature error. The default is 1.0E-06.
        maxiter (int, optional): Max number of iterations. The default is 64.
        return_err (bool, optional): Return final error on intensity to check convergence. The default is False.
        return_power (bool, optional): Return power term values. The default is True.

    Returns:
        dict[str, np.ndarray]: A dictionary with maximum intensity and other results (depending on inputs) in the keys,
        along with input data.

    """

    # save transit in arg
    transit = self.args.transit

    # solve with bisection
    shape = (self.args.get_number_of_computations(),)
    T_ = max_conductor_temperature * np.ones(shape)
    joule_heating = (
        self.convective_cooling.value(T_)
        + self.radiative_cooling.value(T_)
        + self.precipitation_cooling.value(T_)
        - self.solar_heating.value(T_)
    )

    def fun(i: floatArray) -> floatArrayLike:
        self.args.transit = i
        self.joule_heating.__init__(**self.args.__dict__)
        return self.joule_heating.value(T_) - joule_heating

    A, err = bisect_v(fun, Imin, Imax, shape, tol, maxiter)

    # restore previous transit
    self.args.transit = transit

    # format output
    result = {VariableType.TRANSIT.value: A}

    self.add_error_and_power_if_needed(
        max_conductor_temperature,
        err,
        result,
        return_err,
        return_power,
    )

    result = self._add_input_data_to_result(result)

    return result

steady_temperature

steady_temperature(
    Tmin: float = default.tmin,
    Tmax: float = default.tmax,
    tol: float = default.tol,
    maxiter: int = default.maxiter,
    return_err: bool = False,
    return_power: bool = True,
) -> dict[str, np.array]

Compute steady-state temperature.

Parameters:

Name Type Description Default

Tmin

float

Lower bound for temperature.

tmin

Tmax

float

Upper bound for temperature.

tmax

tol

float

Tolerance for temperature error.

tol

maxiter

int

Max number of iterations.

maxiter

return_err

bool

Return final error on temperature to check convergence. The default is False.

False

return_power

bool

Return power term values. The default is True.

True

Returns:

Type Description
dict[str, array]

dict[str, np.array]: A dictionary with temperature and other results (depending on inputs) in the keys,

dict[str, array]

along with input data.

Source code in src/thermohl/solver/slv1t.py
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
def steady_temperature(
    self,
    Tmin: float = default.tmin,
    Tmax: float = default.tmax,
    tol: float = default.tol,
    maxiter: int = default.maxiter,
    return_err: bool = False,
    return_power: bool = True,
) -> dict[str, np.array]:
    """
    Compute steady-state temperature.

    Args:
        Tmin (float, optional): Lower bound for temperature.
        Tmax (float, optional): Upper bound for temperature.
        tol (float, optional): Tolerance for temperature error.
        maxiter (int, optional): Max number of iterations.
        return_err (bool, optional): Return final error on temperature to check convergence. The default is False.
        return_power (bool, optional): Return power term values. The default is True.

    Returns:
        dict[str, np.array]: A dictionary with temperature and other results (depending on inputs) in the keys,
        along with input data.

    """

    # solve with bisection
    conductor_temperature, err = bisect_v(
        lambda x: -self.balance(x),
        Tmin,
        Tmax,
        (self.args.get_number_of_computations(),),
        tol,
        maxiter,
    )

    # format output
    result = {
        VariableType.TEMPERATURE.value: conductor_temperature,
    }
    self.add_error_and_power_if_needed(
        conductor_temperature, err, result, return_err, return_power
    )
    result = self._add_input_data_to_result(result)
    return result

transient_temperature

transient_temperature(
    offset: floatArray = np.array([]),
    T0: Optional[float] = None,
    return_power: bool = False,
) -> dict[str, np.ndarray]

Compute transient-state temperature.

Parameters:

Name Type Description Default

offset

ndarray

A 1D array with times (in seconds) when the temperature needs to be computed. The array must contain increasing values (undefined behaviour otherwise).

array([])

T0

float | None

Initial temperature. If None, the ambient temperature from the internal dict will be used. The default is None.

None

return_power

bool

Return power term values. The default is False.

False

Returns:

Type Description
dict[str, ndarray]

dict[str, np.ndarray]: A dictionary with temperature and other results (depending on inputs) in the keys, along with input data.

Source code in src/thermohl/solver/slv1t.py
 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
def transient_temperature(
    self,
    offset: floatArray = np.array([]),
    T0: Optional[float] = None,
    return_power: bool = False,
) -> dict[str, np.ndarray]:
    """
    Compute transient-state temperature.

    Args:
        offset (numpy.ndarray): A 1D array with times (in seconds) when the temperature needs to be computed. The array must contain increasing values (undefined behaviour otherwise).
        T0 (float | None): Initial temperature. If None, the ambient temperature from the internal dict will be used. The default is None.
        return_power (bool, optional): Return power term values. The default is False.

    Returns:
        dict[str, np.ndarray]: A dictionary with temperature and other results (depending on inputs) in the keys, along with input data.
    """

    # get sizes
    n = self.args.get_number_of_computations()
    N = len(offset)
    if N < 2:
        raise ValueError("The length of the time array must be at least 2.")

    # get initial temperature
    if T0 is None:
        T0 = (
            self.args.ambient_temperature
            if isinstance(self.args.ambient_temperature, numbers.Number)
            else self.args.ambient_temperature[0]
        )
    time_changing_parameters = get_time_changing_parameters(self.args, offset, N, n)
    # inverse of m*C : shortcuts for time-loop
    imc = 1.0 / (self.args.linear_mass * self.args.heat_capacity)

    # init
    conductor_temperature = np.zeros((N, n))
    conductor_temperature[0, :] = T0

    # main time loop
    for i in range(1, N):
        for k, v in time_changing_parameters.items():
            self.args[k] = v[i, :]
        self.update()
        conductor_temperature[i, :] = (
            conductor_temperature[i - 1, :]
            + (offset[i] - offset[i - 1])
            * self.balance(conductor_temperature[i - 1, :])
            * imc
        )

    # save results
    result = {
        VariableType.TIME.value: offset,
        VariableType.TEMPERATURE.value: conductor_temperature,
    }

    # manage return dict 2: powers
    if return_power:
        for power in Solver_.powers():
            result[power.value] = np.zeros_like(conductor_temperature)
        for i in range(N):
            for key in time_changing_parameters.keys():
                self.args[key] = time_changing_parameters[key][i, :]
            self.update()
            result[PowerType.JOULE.value][i, :] = self.joule_heating.value(
                conductor_temperature[i, :]
            )
            result[PowerType.SOLAR.value][i, :] = self.solar_heating.value(
                conductor_temperature[i, :]
            )
            result[PowerType.CONVECTION.value][i, :] = (
                self.convective_cooling.value(conductor_temperature[i, :])
            )
            result[PowerType.RADIATION.value][i, :] = self.radiative_cooling.value(
                conductor_temperature[i, :]
            )
            result[PowerType.RAIN.value][i, :] = self.precipitation_cooling.value(
                conductor_temperature[i, :]
            )

    # squeeze return values if n is 1
    if n == 1:
        keys = list(result.keys())
        keys.remove(VariableType.TIME.value)
        for key in keys:
            result[key] = result[key][:, 0]

    result = self._add_input_data_to_result(result)

    return result