Coverage for pyrc \ core \ components \ input.py: 84%
32 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-13 16:59 +0200
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-13 16:59 +0200
1# -------------------------------------------------------------------------------
2# Copyright (C) 2026 Joel Kimmich, Tim Jourdan
3# ------------------------------------------------------------------------------
4# License
5# This file is part of PyRC, distributed under GPL-3.0-or-later.
6# ------------------------------------------------------------------------------
8from __future__ import annotations
10from abc import abstractmethod
12from pyrc.core.settings import Settings, initial_settings
15class Input:
16 """
17 Each Input can be called as function to get its value during solving depending on the time step/ temperature
18 or last input value.
20 Attributes
21 ----------
22 self.static : bool, optional
23 If True, a static value is assumed and no time-dependent calculations were done.
24 NOTE: You may take a look on the ConstantInput class for such cases to remain performant.
25 This also serves as a switch to first just use static values during network solving until a stationary
26 state is reached and then activate the dynamic calculation.
29 """
31 def __init__(self, settings: Settings = initial_settings):
32 """
33 Super class for all inputs.
35 Mainly used for calculation boundary conditions both time-independent and time-dependent.
37 The simplest way of using this class would be to just return one static value, no matter which solving time,
38 temperature or input_vector is given. Because the __call__method is run every solver iteration it should be
39 as performant as possible. Therefor, for constant Inputs it's recommended to use the ConstantInput class.
41 """
42 self.settings = settings
44 @property
45 def static(self):
46 return self.settings.calculate_static
48 @property
49 @abstractmethod
50 def index(self) -> int:
51 """
52 Returns the index of self in the input vector/matrix.
54 Returns
55 -------
56 int :
57 The index of self in the input vector/matrix.
58 """
59 pass
61 @property
62 @abstractmethod
63 def initial_value(self):
64 pass
66 @initial_value.setter
67 @abstractmethod
68 def initial_value(self, value):
69 pass
71 @abstractmethod
72 def calculate_static(self, tau, temp_vector, _input_vector, *args, **kwargs):
73 """
74 Calculate static values.
76 Each function in the dict must have the possibility to get along with *args and **kwargs.
78 Parameters
79 ----------
80 tau
81 temp_vector
82 _input_vector
83 kwargs
85 Returns
86 -------
88 """
89 pass
91 def calculate_dynamic(self, tau, temp_vector, _input_vector, *args, **kwargs):
92 """
93 Should be overwritten for all time-dependent inputs.
95 Is used, when self.static = False to calculate time-dependent inputs.
97 Each function in the dict must have the possibility to get along with *args and **kwargs.
99 Parameters
100 ----------
101 tau : float
102 The current time of the solving process.
103 temp_vector : np.ndarray
104 The temperature vector of the last solution during iteration.
105 In the first iteration it is the initial one.
106 _input_vector :
107 The input vector used for the last solution during iteration.
108 In the first iteration it is the initial one.
109 kwargs : dict, optional
110 Further values that can be used for just some calculations.
112 Returns
113 -------
114 float | int | np.number :
115 A new input value for the input vector
116 """
117 return self.calculate_static(tau, temp_vector, _input_vector)
119 def get_kwargs_functions(self) -> dict:
120 """
121 Used to calculate keyword arguments for calculate_static/dynamic that only need to be calculated once for all objects.
123 The main reason for this method is speed up during calculation/iteration/solving, because some/most of the
124 boundary conditions only need to be calculated once per time step. So these BCs should be calculated in here
125 and passed to each Input object so that they can use the value for their calculation.
127 Each function in the dict must have the possibility to get along with *args and **kwargs.
129 Returns
130 -------
131 dict :
132 The names of the values that must be passed to calculate_static/dynamic and the function to calculate
133 this values.
134 If for example the exterior temperature is needed for calculate_dynamic, the dict looks like this:
135 {"exterior_temperature": lambda tau: my_fancy_algorithm_to_calculate/get_the_exterior_temperature(tau)}
136 To use it, this dict must be passed to calculate_dynamic like this:
137 my_obj.calculate_dynamic(tau, temp_vector, _input_vector, **the_get_kwargs_dict)
138 """
139 return {}
141 def __call__(self, tau, temp_vector, _input_vector, *args, **kwargs):
142 if self.static:
143 return self.calculate_static(tau, temp_vector, _input_vector, *args, **kwargs)
144 return self.calculate_dynamic(tau, temp_vector, _input_vector, *args, **kwargs)