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
« 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# ------------------------------------------------------------------------------
8# Script for validation
9#
10# Calculation of the solution of stationary heat conduction in different materials
11#
12# Model solution
13#
15import numpy as np
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
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
32class ConductionNetwork(NetworkTemplate):
33 def __init__(self, layers: list[Layer], set_increments_intelligent=False, increment_basic_number: int = 3):
34 super().__init__()
36 self.settings.solve_settings.atol = 1e-8
38 self.save_to_pickle = True
39 self.load_from_pickle = True
40 self.load_solution = True
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]])
52 self.initial_temperature = 0
53 self.lower_temperature = -11
54 self.upper_temperature = 20
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 )
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])
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)
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 )
119 self.groups["layers"] = layer_nodes
120 self.groups["boundaries"] = [lower_temp_bc, upper_temp_bc]
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 )
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, :]
152if __name__ == '__main__':
153 run_conduction_model(True)