pyroll-ring-model-thermal 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ VERSION = "2.0.0"
2
+
3
+ from . import profile
4
+ from . import roll_pass
5
+ from . import transport
6
+ from .config import Config
7
+
8
+ from pyroll.core import root_hooks, Unit
9
+
10
+ root_hooks.add(Unit.OutProfile.temperature)
11
+ root_hooks.add(Unit.OutProfile.ring_temperatures)
12
+
13
+ import importlib.util
14
+
15
+ REPORT_INSTALLED = bool(importlib.util.find_spec("pyroll.report"))
16
+
17
+ if REPORT_INSTALLED:
18
+ from . import report
19
+ import pyroll.report
20
+
21
+ pyroll.report.plugin_manager.register(report)
@@ -0,0 +1,10 @@
1
+ from pyroll.core import config
2
+
3
+
4
+ @config("PYROLL_RING_MODEL_THERMAL")
5
+ class Config:
6
+ RADIATION_COEFFICIENT = 5.670374419e-8
7
+ """The Stefan-Boltzmann radiation constant. Only to change if not working with SI-units."""
8
+
9
+ ROLL_PASS_ATMOSPHERE_TRANSFER = True
10
+ """Whether to include the heat transfer to atmosphere at free surfaces in roll passes into the calculation."""
@@ -0,0 +1,52 @@
1
+ import numpy as np
2
+ from pyroll.core import Profile, Unit
3
+ from pyroll.core.hooks import Hook
4
+ from pyroll.ring_model import RingProfile
5
+
6
+
7
+ @Profile.extension_class
8
+ class Profile(RingProfile):
9
+ ring_temperatures = Hook[np.ndarray]()
10
+ """Array temperature values from core to surface."""
11
+
12
+ relative_radiation_coefficient = Hook[float]()
13
+ """Heat transfer coefficient by convection to atmosphere."""
14
+
15
+
16
+ @Profile.relative_radiation_coefficient
17
+ def relative_radiation_coefficient(self: Profile):
18
+ return 0.8
19
+
20
+
21
+ @Profile.ring_temperatures
22
+ def homogeneous_profile(self: Profile):
23
+ if self.has_set_or_cached("temperature"):
24
+ return np.full_like(self.rings, self.temperature)
25
+
26
+
27
+ @Unit.OutProfile.ring_temperatures
28
+ def out_ring_temperatures_from_in(self: Unit.OutProfile):
29
+ if self.unit.in_profile.has_set_or_cached("ring_temperatures"):
30
+ return np.copy(self.unit.in_profile.ring_temperatures)
31
+
32
+
33
+ @Profile.temperature
34
+ def mean_temperature(self: Profile):
35
+ return np.sum(self.ring_temperatures * [s.area for s in self.ring_sections]) / np.sum(
36
+ [s.area for s in self.ring_sections])
37
+
38
+
39
+ @Profile.surface_temperature
40
+ def surface_temperature(self: Profile):
41
+ return self.ring_temperatures[-1]
42
+
43
+
44
+ @Profile.core_temperature
45
+ def core_temperature(self: Profile):
46
+ return self.ring_temperatures[0]
47
+
48
+
49
+ @Unit.OutProfile.ring_temperatures
50
+ def ring_temperatures_from_disks(self: Unit.OutProfile):
51
+ if self.unit.subunits:
52
+ return self.unit.subunits[-1].out_profile.ring_temperatures
@@ -0,0 +1,129 @@
1
+ import numpy as np
2
+ from pyroll.report import hookimpl
3
+ from pyroll.core import Unit, PassSequence
4
+ from pyroll.core import DiskElementUnit
5
+ import matplotlib as mpl
6
+ import matplotlib.pyplot as plt
7
+ import matplotlib.collections as mcol
8
+
9
+
10
+ @hookimpl(specname="unit_plot")
11
+ def disked_unit_temperature_plot(unit: Unit):
12
+ if isinstance(unit, DiskElementUnit):
13
+ fig: plt.Figure = plt.figure()
14
+ ax: plt.Axes = fig.subplots()
15
+
16
+ count = len(unit.subunits) + 2
17
+ cmap = mpl.colormaps['coolwarm_r']
18
+ colors = cmap(np.linspace(0, 1, count))
19
+
20
+ def prepare_data(p):
21
+ return (
22
+ np.append(p.rings, p.equivalent_radius) / p.equivalent_radius,
23
+ np.append(p.ring_temperatures, p.surface_temperature)
24
+ )
25
+
26
+ ip = ax.plot(*prepare_data(unit.in_profile), c=colors[0], label="incoming profile")[0]
27
+
28
+ for i in range(1, count - 1):
29
+ u = unit.subunits[i - 1]
30
+ ax.plot(*prepare_data(u.out_profile), c=colors[i])
31
+
32
+ op = ax.plot(*prepare_data(unit.out_profile), c=colors[-1], label="outgoing profile")[0]
33
+
34
+ ax.set_title("Radial Temperature Profile Evolution")
35
+ ax.set_xlabel("Relative Distance from Core")
36
+ ax.set_ylabel("Temperature")
37
+
38
+ lc = mcol.LineCollection(
39
+ 5 * [[(0, 0)]],
40
+ colors=cmap(np.linspace(0, 1, 7)[1:-1]),
41
+ label="intermediate stages",
42
+ )
43
+
44
+ ax.legend(handles=[ip, lc, op], handler_map={type(lc): HandlerDashedLines()})
45
+
46
+ return fig
47
+
48
+
49
+ @hookimpl(specname="unit_plot")
50
+ def pass_sequence_temperature_plot(unit: Unit):
51
+ if isinstance(unit, PassSequence):
52
+ fig: plt.Figure = plt.figure()
53
+ ax: plt.Axes = fig.subplots()
54
+
55
+ def yield_data(u: Unit, name):
56
+ yield getattr(u.in_profile, name, None)
57
+ if u.subunits:
58
+ for su in u.subunits:
59
+ yield from yield_data(su, name)
60
+ yield getattr(u.out_profile, name, None)
61
+
62
+ t = np.array(list(yield_data(unit, "t")))
63
+ core = np.array(list(yield_data(unit, "core_temperature")))
64
+ surface = np.array(list(yield_data(unit, "surface_temperature")))
65
+ mean = np.array(list(yield_data(unit, "temperature")))
66
+
67
+ ax.plot(t, core, label="core")
68
+ ax.plot(t, surface, label="surface")
69
+ ax.plot(t, mean, label="mean")
70
+
71
+ ax.legend()
72
+
73
+ ax.set_title("Temperature Evolution")
74
+ ax.set_xlabel("Cumulative Process Time $t$")
75
+ ax.set_ylabel("Temperature $T$")
76
+
77
+ return fig
78
+
79
+
80
+ # from https://matplotlib.org/stable/gallery/text_labels_and_annotations/legend_demo.html#sphx-glr-gallery-text-labels-and-annotations-legend-demo-py
81
+ from matplotlib.legend_handler import HandlerLineCollection
82
+ from matplotlib.lines import Line2D
83
+
84
+
85
+ class HandlerDashedLines(HandlerLineCollection):
86
+ """
87
+ Custom Handler for LineCollection instances.
88
+ """
89
+
90
+ def create_artists(
91
+ self, legend, orig_handle,
92
+ xdescent, ydescent, width, height, fontsize, trans
93
+ ):
94
+ # figure out how many lines there are
95
+ numlines = len(orig_handle.get_segments())
96
+ xdata, xdata_marker = self.get_xdata(
97
+ legend, xdescent, ydescent,
98
+ width, height, fontsize
99
+ )
100
+ leglines = []
101
+ # divide the vertical space where the lines will go
102
+ # into equal parts based on the number of lines
103
+ ydata = np.full_like(xdata, height / (numlines + 1))
104
+ # for each line, create the line at the proper location
105
+ # and set the dash pattern
106
+ for i in range(numlines):
107
+ legline = Line2D(xdata, ydata * (numlines - i) - ydescent)
108
+ self.update_prop(legline, orig_handle, legend)
109
+ # set color, dash pattern, and linewidth to that
110
+ # of the lines in linecollection
111
+ try:
112
+ color = orig_handle.get_colors()[i]
113
+ except IndexError:
114
+ color = orig_handle.get_colors()[0]
115
+ try:
116
+ dashes = orig_handle.get_dashes()[i]
117
+ except IndexError:
118
+ dashes = orig_handle.get_dashes()[0]
119
+ try:
120
+ lw = orig_handle.get_linewidths()[i]
121
+ except IndexError:
122
+ lw = orig_handle.get_linewidths()[0]
123
+ if dashes[1] is not None:
124
+ legline.set_dashes(dashes[1])
125
+ legline.set_color(color)
126
+ legline.set_transform(trans)
127
+ legline.set_linewidth(lw)
128
+ leglines.append(legline)
129
+ return leglines
@@ -0,0 +1,207 @@
1
+ from typing import Union, Tuple
2
+
3
+ import numpy as np
4
+
5
+ from .config import Config
6
+ from .profile import Profile
7
+ from pyroll.core import RollPass, Unit, Hook, DeformationUnit
8
+ import scipy.optimize as scopt
9
+
10
+
11
+ @RollPass.Roll.extension_class
12
+ class RollExt(RollPass.Roll):
13
+ heat_transfer_coefficient = Hook[float]()
14
+ """Heat transfer coefficient by contact to the roll."""
15
+
16
+
17
+ @RollPass.extension_class
18
+ class RollPassExt(RollPass):
19
+ heat_transfer_coefficient = Hook[float]()
20
+ """Heat transfer coefficient by convection to atmosphere."""
21
+
22
+ deformation_heat_efficiency = Hook[float]()
23
+ """Efficiency of heat generation by deformation power."""
24
+
25
+ environment_temperature = Hook[float]()
26
+ """Temperature of the surrounding atmosphere."""
27
+
28
+
29
+ @RollPassExt.deformation_heat_efficiency
30
+ def deformation_heat_efficiency(self: RollPass):
31
+ return 0.95
32
+
33
+
34
+ @RollPassExt.environment_temperature
35
+ def environment_temperature(self: RollPassExt):
36
+ return self.roll.temperature
37
+
38
+
39
+ @RollExt.heat_transfer_coefficient
40
+ def heat_transfer_coefficient(self: RollPass):
41
+ return 6000
42
+
43
+
44
+ @RollPassExt.heat_transfer_coefficient
45
+ def heat_transfer_coefficient(self: RollPass):
46
+ return 150
47
+
48
+
49
+ def get_increments(unit: DeformationUnit, roll_pass: RollPassExt, ring_temperatures) -> np.ndarray:
50
+ p: Profile = unit.in_profile
51
+
52
+ increments = np.zeros_like(ring_temperatures)
53
+
54
+ deformation_resistance = (
55
+ unit.deformation_resistance
56
+ if unit.has_value("deformation_resistance")
57
+ else (unit.in_profile.flow_stress + 2 * unit.out_profile.flow_stress) / 3
58
+ )
59
+
60
+ source_density = roll_pass.deformation_heat_efficiency * deformation_resistance * unit.strain_rate
61
+
62
+ cross_section = p.ring_sections[0].area
63
+ increments[0] = unit.duration / (p.density * p.thermal_capacity * cross_section) * (
64
+ (ring_temperatures[1] - ring_temperatures[0]) * p.ring_contours[1].length
65
+ / p.rings[1] * p.thermal_conductivity
66
+ + source_density * cross_section
67
+ )
68
+
69
+ try:
70
+ free_surface_ratio = unit.free_surface_area / unit.surface_area
71
+ except AttributeError:
72
+ free_surface_ratio = 0
73
+
74
+ cross_section = p.ring_sections[-1].area
75
+
76
+ roll_contact_transfer = (
77
+ roll_pass.roll.heat_transfer_coefficient * (roll_pass.roll.temperature - p.surface_temperature)
78
+ * p.ring_contours[-1].length * (1 - free_surface_ratio)
79
+ )
80
+
81
+ if Config.ROLL_PASS_ATMOSPHERE_TRANSFER:
82
+ atmosphere_transfer = (
83
+ (
84
+ roll_pass.heat_transfer_coefficient
85
+ * (roll_pass.environment_temperature - p.surface_temperature)
86
+ + Config.RADIATION_COEFFICIENT * p.relative_radiation_coefficient
87
+ * (roll_pass.environment_temperature ** 4 - p.surface_temperature ** 4)
88
+ )
89
+ * p.ring_contours[-1].length * free_surface_ratio
90
+ )
91
+ else:
92
+ atmosphere_transfer = 0
93
+
94
+ increments[-1] = unit.duration / (p.density * p.thermal_capacity * cross_section) * (
95
+ roll_contact_transfer + atmosphere_transfer
96
+ - p.thermal_conductivity * (ring_temperatures[-1] - ring_temperatures[-2])
97
+ / (p.rings[-1] - p.rings[-2])
98
+ * p.ring_contours[-2].length
99
+ + source_density * cross_section
100
+ )
101
+
102
+ for i in range(1, len(increments) - 1):
103
+ cross_section = p.ring_sections[i].area
104
+ increments[i] = unit.duration / (p.density * p.thermal_capacity * cross_section) * (
105
+ p.thermal_conductivity
106
+ * (
107
+ (ring_temperatures[i + 1] - ring_temperatures[i]) * p.ring_contours[i + 1].length
108
+ / (p.rings[i + 1] - p.rings[i])
109
+ - (ring_temperatures[i] - ring_temperatures[i - 1]) * p.ring_contours[i].length
110
+ / (p.rings[i] - p.rings[i - 1])
111
+ )
112
+ + source_density * cross_section
113
+ )
114
+
115
+ return increments
116
+
117
+
118
+ def _solve_step(unit, roll_pass, in_ring_temperatures):
119
+ x0 = get_increments(unit, roll_pass, in_ring_temperatures)
120
+
121
+ def f(x):
122
+ out_ring_temperatures = in_ring_temperatures + x
123
+ return get_increments(unit, roll_pass, out_ring_temperatures) - x
124
+
125
+ sol = scopt.root(f, x0=x0)
126
+
127
+ if not sol.success:
128
+ raise RuntimeError(f"Numerical procedure did not succeed: {sol.message}.")
129
+
130
+ return in_ring_temperatures + sol.x
131
+
132
+
133
+ @RollPass.OutProfile.ring_temperatures
134
+ def ring_temperatures_disk(self: Union[RollPass.OutProfile, Profile]):
135
+ if not self.roll_pass.disk_elements:
136
+ roll_pass = self.roll_pass
137
+
138
+ return _solve_step(roll_pass, roll_pass, roll_pass.in_profile.ring_temperatures)
139
+
140
+
141
+ @RollPass.DiskElement.OutProfile.ring_temperatures
142
+ def ring_temperatures_disk(self: Union[RollPass.DiskElement.OutProfile, Profile]):
143
+ roll_pass = self.roll_pass
144
+ disk = self.disk_element
145
+
146
+ return _solve_step(disk, roll_pass, disk.in_profile.ring_temperatures)
147
+
148
+
149
+ def _surface_temperature(self: Union[RollPass.Profile, Profile]):
150
+ roll_pass: RollPassExt = self.roll_pass
151
+
152
+ try:
153
+ free_surface_ratio = roll_pass.free_surface_area / roll_pass.surface_area
154
+ except AttributeError:
155
+ free_surface_ratio = 0
156
+
157
+ def f(ts):
158
+ roll_contact_transfer = (
159
+ roll_pass.roll.heat_transfer_coefficient * (roll_pass.roll.temperature - ts)
160
+ * self.ring_contours[-1].length * (1 - free_surface_ratio)
161
+ )
162
+
163
+ if Config.ROLL_PASS_ATMOSPHERE_TRANSFER:
164
+ atmosphere_transfer = (
165
+ (
166
+ roll_pass.heat_transfer_coefficient
167
+ * (roll_pass.environment_temperature - ts)
168
+ + Config.RADIATION_COEFFICIENT * self.relative_radiation_coefficient
169
+ * (roll_pass.environment_temperature ** 4 - ts ** 4)
170
+ )
171
+ * self.ring_contours[-1].length * free_surface_ratio
172
+ )
173
+ else:
174
+ atmosphere_transfer = 0
175
+
176
+ return (
177
+ roll_contact_transfer + atmosphere_transfer
178
+ - self.thermal_conductivity
179
+ * (ts - self.ring_temperatures[-1])
180
+ / (self.equivalent_radius - self.rings[-1])
181
+ )
182
+
183
+ def fprime(ts):
184
+ return (
185
+ - roll_pass.roll.heat_transfer_coefficient * (1 - free_surface_ratio)
186
+ - ((
187
+ roll_pass.heat_transfer_coefficient
188
+ + 4 * Config.RADIATION_COEFFICIENT * self.relative_radiation_coefficient
189
+ * ts ** 3
190
+ ) * free_surface_ratio if Config.ROLL_PASS_ATMOSPHERE_TRANSFER else 0)
191
+ - self.thermal_conductivity / (self.equivalent_radius - self.rings[-1])
192
+ )
193
+
194
+ sol = scopt.root_scalar(f=f, fprime=fprime, x0=self.ring_temperatures[-1], method="newton")
195
+
196
+ if sol.converged:
197
+ return sol.root
198
+
199
+
200
+ @RollPass.Profile.surface_temperature
201
+ def surface_temperature(self: Union[RollPass.Profile, Profile]):
202
+ return _surface_temperature(self)
203
+
204
+
205
+ @RollPass.DiskElement.Profile.surface_temperature
206
+ def disk_surface_temperature(self: Union[RollPass.Profile, Profile]):
207
+ return _surface_temperature(self)
@@ -0,0 +1,133 @@
1
+ from typing import Union
2
+
3
+ import numpy as np
4
+ import scipy.optimize as scopt
5
+ from pyroll.core import Transport, Unit, Hook
6
+
7
+ from .config import Config
8
+ from .profile import Profile
9
+
10
+
11
+ @Transport.extension_class
12
+ class TransportExt(Transport):
13
+ heat_transfer_coefficient = Hook[float]()
14
+ """Heat transfer coefficient by convection to atmosphere."""
15
+
16
+
17
+ @TransportExt.heat_transfer_coefficient
18
+ def heat_transfer_coefficient(self: Transport):
19
+ return 15
20
+
21
+
22
+ def get_increments(unit: Unit, transport: TransportExt, ring_temperatures) -> np.ndarray:
23
+ p: Profile = unit.out_profile
24
+
25
+ increments = np.zeros_like(ring_temperatures)
26
+
27
+ source_density = 0 # TODO source density term in W / m^3
28
+
29
+ cross_section = p.ring_sections[0].area
30
+ increments[0] = unit.duration / (p.density * p.thermal_capacity * cross_section) * (
31
+ (ring_temperatures[1] - ring_temperatures[0]) * p.ring_contours[1].length
32
+ / p.rings[1] * p.thermal_conductivity
33
+ + source_density * cross_section
34
+ )
35
+
36
+ cross_section = p.ring_sections[-1].area
37
+ increments[-1] = unit.duration / (p.density * p.thermal_capacity * cross_section) * (
38
+ (
39
+ transport.heat_transfer_coefficient
40
+ * (transport.environment_temperature - p.surface_temperature)
41
+ + Config.RADIATION_COEFFICIENT * p.relative_radiation_coefficient
42
+ * (transport.environment_temperature ** 4 - p.surface_temperature ** 4)
43
+ )
44
+ * p.ring_contours[-1].length
45
+ - p.thermal_conductivity * (ring_temperatures[-1] - ring_temperatures[-2])
46
+ / (p.rings[-1] - p.rings[-2])
47
+ * p.ring_contours[-2].length
48
+ + source_density * cross_section
49
+ )
50
+
51
+ for i in range(1, len(increments) - 1):
52
+ cross_section = p.ring_sections[i].area
53
+ increments[i] = unit.duration / (p.density * p.thermal_capacity * cross_section) * (
54
+ p.thermal_conductivity
55
+ * (
56
+ (ring_temperatures[i + 1] - ring_temperatures[i]) * p.ring_contours[i + 1].length
57
+ / (p.rings[i + 1] - p.rings[i])
58
+ - (ring_temperatures[i] - ring_temperatures[i - 1]) * p.ring_contours[i].length
59
+ / (p.rings[i] - p.rings[i - 1])
60
+ )
61
+ + source_density * cross_section
62
+ )
63
+
64
+ return increments
65
+
66
+
67
+ def _solve_step(unit, transport, in_ring_temperatures):
68
+ x0 = get_increments(unit, transport, in_ring_temperatures)
69
+
70
+ def f(x):
71
+ out_ring_temperatures = in_ring_temperatures + x
72
+ return get_increments(unit, transport, out_ring_temperatures) - x
73
+
74
+ sol = scopt.root(f, x0=x0)
75
+
76
+ if not sol.success:
77
+ raise RuntimeError(f"Numerical procedure did not succeed: {sol.message}.")
78
+
79
+ return in_ring_temperatures + sol.x
80
+
81
+
82
+ @Transport.OutProfile.ring_temperatures
83
+ def ring_temperatures_disk(self: Union[Transport.OutProfile, Profile]):
84
+ if not self.transport.disk_elements:
85
+ transport = self.transport
86
+
87
+ return _solve_step(transport, transport, transport.in_profile.ring_temperatures)
88
+
89
+
90
+ @Transport.DiskElement.OutProfile.ring_temperatures
91
+ def ring_temperatures_disk(self: Union[Transport.DiskElement.OutProfile, Profile]):
92
+ transport = self.transport
93
+ disk = self.disk_element
94
+
95
+ return _solve_step(disk, transport, disk.in_profile.ring_temperatures)
96
+
97
+
98
+ def _surface_temperature(self: Union[Transport.Profile, Profile]):
99
+ transport: TransportExt = self.transport
100
+
101
+ def f(ts):
102
+ return (
103
+ transport.heat_transfer_coefficient
104
+ * (transport.environment_temperature - ts)
105
+ + Config.RADIATION_COEFFICIENT * self.relative_radiation_coefficient
106
+ * (transport.environment_temperature ** 4 - ts ** 4)
107
+ - self.thermal_conductivity
108
+ * (ts - self.ring_temperatures[-1])
109
+ / (self.equivalent_radius - self.rings[-1])
110
+ )
111
+
112
+ def fprime(ts):
113
+ return (
114
+ -4 * Config.RADIATION_COEFFICIENT * self.relative_radiation_coefficient
115
+ * ts ** 3
116
+ - transport.heat_transfer_coefficient
117
+ - self.thermal_conductivity / (self.equivalent_radius - self.rings[-1])
118
+ )
119
+
120
+ sol = scopt.root_scalar(f=f, fprime=fprime, x0=self.ring_temperatures[-1], method="newton")
121
+
122
+ if sol.converged:
123
+ return sol.root
124
+
125
+
126
+ @Transport.Profile.surface_temperature
127
+ def surface_temperature(self: Union[Transport.Profile, Profile]):
128
+ return _surface_temperature(self)
129
+
130
+
131
+ @Transport.DiskElement.Profile.surface_temperature
132
+ def disk_surface_temperature(self: Union[Transport.Profile, Profile]):
133
+ return _surface_temperature(self)
@@ -0,0 +1,10 @@
1
+ Metadata-Version: 2.1
2
+ Name: pyroll-ring-model-thermal
3
+ Version: 2.0.0
4
+ Summary: Plugin for PyRoll providing a radial thermal approach based on the ring model.
5
+ Author-email: Max Weiner <max.weiner@imf.tu-freiberg.de>
6
+ License-Expression: BSD-3-Clause
7
+ License-File: LICENSE
8
+ Requires-Python: <4.0,>=3.9
9
+ Requires-Dist: pyroll-core~=2.0
10
+ Requires-Dist: pyroll-ring-model~=2.0
@@ -0,0 +1,10 @@
1
+ pyroll/ring_model_thermal/__init__.py,sha256=qbbGudfCewqkZOijlLcruoQ_rC3GqmYnF3viq18-tLk,467
2
+ pyroll/ring_model_thermal/config.py,sha256=-_4WFcZNqAiFkukexpMb_ygZNi69CigBF782JEDdIeU,380
3
+ pyroll/ring_model_thermal/profile.py,sha256=u5z9NadWPQyWBDluy_QDj04KDfZoFdKpjKx7LQ3cCnc,1510
4
+ pyroll/ring_model_thermal/report.py,sha256=PHH2gxlbCsH-kUlLyE4qeYH4P0KTSFuKXmhnHaEGcv4,4573
5
+ pyroll/ring_model_thermal/roll_pass.py,sha256=oCyxnv4rRSHsqKXYzK7WAvaiDnLlfk-cRHEbFL7Wxl8,7288
6
+ pyroll/ring_model_thermal/transport.py,sha256=8be2cDEjzRGZTtwAQ_lDUcjnVopHZWA-IH2aEFcvWSY,4759
7
+ pyroll_ring_model_thermal-2.0.0.dist-info/METADATA,sha256=_X9TOMQPU-sAgGJSHDLluRS-Z8IXhm78AXmR3gXeLKc,367
8
+ pyroll_ring_model_thermal-2.0.0.dist-info/WHEEL,sha256=9QBuHhg6FNW7lppboF2vKVbCGTVzsFykgRQjjlajrhA,87
9
+ pyroll_ring_model_thermal-2.0.0.dist-info/licenses/LICENSE,sha256=cC-Hopqx0dkfeivDS5kNfOOAZ-IBvUe5BEF4z9MY1Mo,1474
10
+ pyroll_ring_model_thermal-2.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.18.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,11 @@
1
+ Copyright 2022 Max Weiner, Christoph Renzing
2
+
3
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
+
5
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6
+
7
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
+
9
+ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
+
11
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.