Coverage for pyrc \ validation \ conduction \ model.py: 0%

66 statements  

« 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# ------------------------------------------------------------------------------ 

7 

8# Script for validation 

9# 

10# Calculation of the solution of stationary heat conduction in different materials 

11# 

12# Model solution 

13# 

14 

15import numpy as np 

16 

17from pyrc.core.inputs import FluidBoundaryConditionGeometric 

18from pyrc.core.nodes import Node 

19from pyrc.core.resistors import HeatConduction, CombinedResistor 

20from pyrc.core.components.templates import Solid 

21from pyrc.visualization.plot import LinePlot 

22from pyrc.validation.network import NetworkTemplate 

23 

24 

25class Layer: 

26 def __init__(self, thickness, thermal_conductivity, number_increments=40): 

27 self.thickness = thickness 

28 self.thermal_conductivity = thermal_conductivity 

29 self.number_increments = number_increments 

30 

31 

32class ConductionNetwork(NetworkTemplate): 

33 def __init__(self, layers: list[Layer], set_increments_intelligent=False, increment_basic_number: int = 3): 

34 super().__init__() 

35 

36 self.settings.solve_settings.atol = 1e-8 

37 

38 self.save_to_pickle = True 

39 self.load_from_pickle = True 

40 self.load_solution = True 

41 

42 self.layers = layers 

43 if set_increments_intelligent: 

44 increment_number = ( 

45 np.ceil(1 / min([layer.thickness / layer.thermal_conductivity for layer in (self.layers)])) 

46 * increment_basic_number 

47 ) 

48 for layer in self.layers: 

49 layer.number_increments = int(np.ceil(layer.thickness / layer.thermal_conductivity * increment_number)) 

50 self.x_major_points = np.cumsum([0, *[l.thickness for l in layers]]) 

51 

52 self.initial_temperature = 0 

53 self.lower_temperature = -11 

54 self.upper_temperature = 20 

55 

56 def _create_network(self, *args, **kwargs): 

57 # first, create the nodes 

58 layer_nodes = [] 

59 layer: Layer 

60 for i, layer, x_start in zip(range(len(self.layers)), self.layers, self.x_major_points): 

61 material = Solid( 

62 f"material_{i}", 

63 thermal_conductivity=layer.thermal_conductivity, 

64 density=10, # Speed up convergence by decreasing mass and heat capacity 

65 heat_capacity=100, 

66 ) 

67 for increment in range(layer.number_increments): 

68 layer_nodes.append( 

69 Node( 

70 material=material, 

71 temperature=self.initial_temperature, 

72 position=np.array( 

73 [x_start + (increment + 0.5) * layer.thickness / layer.number_increments, 0, 0] 

74 ), 

75 delta=(layer.thickness / layer.number_increments, 1, 1), 

76 rc_objects=self.rc_objects, 

77 rc_solution=self.rc_solution, 

78 ) 

79 ) 

80 

81 # add resistors between the nodes. 

82 all_resistors = [] 

83 for i, node in enumerate(layer_nodes[:-1]): 

84 all_resistors.append(HeatConduction()) 

85 all_resistors[-1].connect(layer_nodes[i]) 

86 all_resistors[-1].connect(layer_nodes[i + 1]) 

87 

88 # add boundary conditions 

89 lower_temp_bc = FluidBoundaryConditionGeometric( 

90 temperature=self.lower_temperature, 

91 position=layer_nodes[0].position + np.array([-1, 0, 0]), 

92 rc_objects=self.rc_objects, 

93 rc_solution=self.rc_solution, 

94 settings=self.settings, 

95 ) 

96 all_resistors.append(CombinedResistor(resistance=np.float64(0))) 

97 all_resistors.append(CombinedResistor()) 

98 all_resistors[-1].connect(layer_nodes[0], direction=(-1, 0, 0), node_direction_points_to=lower_temp_bc) 

99 all_resistors[-1].connect(all_resistors[-2]) 

100 all_resistors[-2].connect(lower_temp_bc) 

101 upper_temp_bc = FluidBoundaryConditionGeometric( 

102 temperature=self.upper_temperature, 

103 position=layer_nodes[-1].position + np.array([1, 0, 0]), 

104 rc_objects=self.rc_objects, 

105 rc_solution=self.rc_solution, 

106 settings=self.settings, 

107 ) 

108 all_resistors.append(CombinedResistor(resistance=np.float64(0))) 

109 all_resistors.append(CombinedResistor()) 

110 all_resistors[-1].connect(layer_nodes[-1], direction=(1, 0, 0), node_direction_points_to=upper_temp_bc) 

111 all_resistors[-1].connect(all_resistors[-2]) 

112 all_resistors[-2].connect(upper_temp_bc) 

113 

114 # add all nodes and resistors to rc_objects 

115 self.rc_objects.set_lists( 

116 capacitors=layer_nodes, resistors=all_resistors, boundaries=[lower_temp_bc, upper_temp_bc] 

117 ) 

118 

119 self.groups["layers"] = layer_nodes 

120 self.groups["boundaries"] = [lower_temp_bc, upper_temp_bc] 

121 

122 

123def run_conduction_model(plot_data=True, calculation_time=12000): 

124 network = ConductionNetwork( 

125 [ 

126 Layer(0.1, 1, number_increments=6), 

127 Layer(0.2, 3, number_increments=5), 

128 Layer(0.5, 10, number_increments=10), 

129 Layer(0.1, 0.3, number_increments=40), 

130 Layer(0.1, 30, number_increments=3), 

131 ], 

132 set_increments_intelligent=True, 

133 increment_basic_number=2, 

134 ) 

135 network.create_network() 

136 network.solve_network( 

137 # t_span=(0, 3600*24*1), 

138 t_span=(0, calculation_time), 

139 print_progress=True, 

140 check_courant=False, 

141 ) 

142 

143 if plot_data: 

144 plot = LinePlot(x=[n.position[0] for n in network.nodes], ys=network.rc_solution.temperature_vectors[-1, :]) 

145 plot.plot() 

146 plot.ax.set_xlim(left=0, right=network.x_major_points[-1]) 

147 plot.save(r"C:\Simulations\PyRC\debug\conduction_model.png") 

148 else: 

149 return [n.position[0] for n in network.nodes], network.rc_solution.temperature_vectors[-1, :] 

150 

151 

152if __name__ == '__main__': 

153 run_conduction_model(True)