Skip to content

Commit

Permalink
Merge pull request #42 from tarao1006/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
tarao1006 authored Jul 14, 2021
2 parents d6ab69f + b37b36c commit 6c29cc9
Show file tree
Hide file tree
Showing 24 changed files with 901 additions and 281 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.2.4
0.3.0
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
author = 'tarao1006'

# The full version, including alpha/beta/rc tags
release = '0.2.4'
release = '0.3.0'


# -- General configuration ---------------------------------------------------
Expand Down
16 changes: 8 additions & 8 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ Getting Started
# 熱交換を行う流体を準備
streams = [
Stream(40.0, 90.0, 150.0, StreamType(1)),
Stream(80.0, 110.0, 180.0, StreamType(1)),
Stream(125.0, 80.0, 180.0, StreamType(2)),
Stream(100.0, 60.0, 160.0, StreamType(2))
Stream(40.0, 90.0, 150.0, StreamType(1), 'cold1'),
Stream(80.0, 110.0, 180.0, StreamType(1), 'cold2'),
Stream(125.0, 80.0, 180.0, StreamType(2), 'hot1'),
Stream(100.0, 60.0, 160.0, StreamType(2), 'hot2')
]
minimum_approach_temperature_difference = 10.0
analyzer = PinchAnalyzer(streams, minimum_approach_temperature_difference)
Expand Down Expand Up @@ -132,10 +132,10 @@ Details
.. code-block:: python
streams = [
Stream(40.0, 90.0, 150.0, StreamType(1)),
Stream(80.0, 110.0, 180.0, StreamType(1)),
Stream(125.0, 80.0, 180.0, StreamType(2)),
Stream(100.0, 60.0, 160.0, StreamType(2))
Stream(40.0, 90.0, 150.0, StreamType(1), 'cold1'),
Stream(80.0, 110.0, 180.0, StreamType(1), 'cold2'),
Stream(125.0, 80.0, 180.0, StreamType(2), 'hot1'),
Stream(100.0, 60.0, 160.0, StreamType(2), 'hot2')
]
``Stream`` のコンストラクタ:
Expand Down
10 changes: 5 additions & 5 deletions examples/simple/data.csv
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
input_temperature,output_temperature,heat_flow,type,cost
40.0,90.0,150.0,1,0
80.0,110.0,180.0,1,0
125.0,80.0,160.0,2,0
100.0,60.0,160.0,2,0
id,input_temperature,output_temperature,heat_flow,type,state,cost,reboiler_or_reactor
a,40.0,90.0,150.0,1,1,0,
b,80.0,110.0,180.0,1,1,0,
A,125.0,80.0,160.0,2,1,0,
B,100.0,60.0,160.0,2,1,0,
38 changes: 35 additions & 3 deletions examples/simple/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,56 @@
import pandas as pd
from matplotlib.collections import LineCollection

from pyheatintegration import (PinchAnalyzer, Stream, StreamType,
from pyheatintegration import (PinchAnalyzer, Stream, StreamState, StreamType,
extract_x, y_range)


def main():
df = pd.read_csv("./data.csv")
df = pd.read_csv("./data.csv").fillna({'reboiler_or_reactor': ''})
streams = [
Stream(
row.input_temperature,
row.output_temperature,
row.heat_flow,
StreamType(row.type),
row.cost
StreamState(row.state),
cost=row.cost,
reboiler_or_reactor=bool(row.reboiler_or_reactor),
id_=row.id
) for _, row in df.iterrows()]

minimum_approach_temperature_difference = 10.0
analyzer = PinchAnalyzer(streams, minimum_approach_temperature_difference)

print(
f"設定可能最小接近温度差 [℃]: {analyzer.minimum_approach_temp_diff_range.start:.3f}"
f" ~ {analyzer.minimum_approach_temp_diff_range.finish:.3f}"
)

print(f'ピンチポイント [℃]: {analyzer.gcc.minimum_pinch_point_temp}')
print(f'必要加熱量[W]: {analyzer.external_heating_demand:.3f}')
print(f'必要冷却量[W]: {analyzer.external_cooling_demand:.3f}')

for stream in analyzer.streams:
if stream.is_external() and stream.is_hot():
print(
f'外部与熱流体 id: {stream.id_} '
'\033[1m加熱量\033[0m [W]: '
f'{stream.heat():.3f} '
'\033[1mコスト\033[0m [円/s]: '
f'{stream.heat() * stream.cost:.3f}'
)

for stream in analyzer.streams:
if stream.is_external() and stream.is_cold():
print(
f'外部受熱流体 id: {stream.id_} '
'\033[1m冷却量\033[0m [W]: '
f'{stream.heat():.3f} '
'\033[1mコスト\033[0m [円/s]: '
f'{stream.heat() * stream.cost:.3f}'
)

# グランドコンポジットカーブ
heats, temps = analyzer.create_grand_composite_curve()
fig, ax = plt.subplots(1, 1)
Expand Down
2 changes: 1 addition & 1 deletion src/pyheatintegration/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .enums import StreamType # noqa
from .enums import StreamState, StreamType # noqa
from .grand_composite_curve import GrandCompositeCurve # noqa
from .line import extract_x, y_range # noqa
from .pinch_analyzer import PinchAnalyzer # noqa
Expand Down
24 changes: 24 additions & 0 deletions src/pyheatintegration/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class StreamType(Enum):
HOT = 2
EXTERNAL_COLD = 3
EXTERNAL_HOT = 4
AUTO = 5

def describe(self) -> str:
return STREAMTYPE_STR[self.name]
Expand All @@ -18,4 +19,27 @@ def describe(self) -> str:
'HOT': 'hot',
'EXTERNAL_COLD': 'external cold',
'EXTERNAL_HOT': 'external hot',
'AUTO': 'auto'
}


class StreamState(Enum):
"""流体の状態"""

LIQUID = 1
GAS = 2
LIQUID_EVAPORATION = 3
GAS_CONDENSATION = 4
UNKNOWN = 5

def describe(self) -> str:
return STREAMSTATE_STR[self.name]


STREAMSTATE_STR = {
'LIQUID': 'liquid',
'GAS': 'gas',
'LIQUID_EVAPORATION': 'liquid (evaporation)',
'GAS_CONDENSATION': 'gas (condensation)',
'UNKNOWN': 'unknown'
}
135 changes: 60 additions & 75 deletions src/pyheatintegration/grand_composite_curve.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,49 @@
from .temperature_range import TemperatureRange, get_temperatures


def _get_heats(
temp_ranges: list[TemperatureRange],
temp_range_streams: defaultdict[TemperatureRange, set[Stream]]
) -> list[float]:
"""温度変化領域ごとの熱量変化を求めます。
Args:
temp_ranges: list[TemperatureRange]: 温度領域のリスト。
temp_range_lacking_heat: dict[TemperatureRange, float]:
温度領域ごとの過不足熱量。
Returns:
list[float]: 熱量のリスト。
"""
temp_range_lacking_heat = _get_lacking_heats(temp_range_streams)

temp_ranges.sort()
heats = [0.0] * (len(temp_ranges) + 1)
for i, temp_range in enumerate(temp_ranges):
heats[i + 1] = heats[i] - temp_range_lacking_heat[temp_range]
min_heat = min(heats)

return [heat - min_heat for heat in heats]


def _get_lacking_heats(
temp_range_streams: defaultdict[TemperatureRange, set[Stream]]
) -> defaultdict[TemperatureRange, float]:
"""温度領域ごとの不足熱量を求めます.
Args:
temp_range_streams defaultdict[float, set[Stream]]:
温度領域ごとの流体のセット。
Returns:
defaultdict[TemperatureRange, float]: 温度領域ごとの過不足熱量。
"""
return defaultdict(int, {
temp_range: sum([s.heat() for s in streams if s.is_hot()]) - sum([s.heat() for s in streams if s.is_cold()])
for temp_range, streams in temp_range_streams.items()
})


class GrandCompositeCurve:
"""グランドコンポジットカーブを作成するために必要な情報を得るためのクラス。
Expand All @@ -21,8 +64,6 @@ class GrandCompositeCurve:
minimum_pinch_point_index (int): 最も温度が低いピンチポイントのインデックス。
temps (list[float]): 温度のリスト[℃]。
heats (list[float]): 熱量のリスト[W]。
hot_utility_target (float): 必要加熱量[W]。
cold_utility_target (float): 必要冷却熱量[W]。
"""

def __init__(
Expand All @@ -48,21 +89,30 @@ def __init__(
stream for stream in streams if stream.is_internal()
])
self.temps = get_temperatures(temp_ranges)
self.heats = self._get_heats(
temp_ranges,
self._lacking_heats(temp_range_streams)
)
self.heats = _get_heats(temp_ranges, temp_range_streams)

pinch_point_info = self._set_pinch_point()
pinch_point_info = self._get_pinch_point()
self.maximum_pinch_point_temp = pinch_point_info[0]
self.maximum_pinch_point_index = pinch_point_info[1]
self.minimum_pinch_point_temp = pinch_point_info[2]
self.minimum_pinch_point_index = pinch_point_info[3]

self.hot_utility_target = self.heats[-1]
self.cold_utility_target = self.heats[0]
def _get_pinch_point(self) -> tuple[float, int, float, int]:
"""ピンチポイントとピンチポイントのインデックスを求めます。
"""
pinch_point_indexes = [
i for i, heat in enumerate(self.heats) if heat == 0
]
pinch_points = [self.temps[i] for i in pinch_point_indexes]

return (
pinch_points[-1],
pinch_point_indexes[-1],
pinch_points[0],
pinch_point_indexes[0]
)

def solve_external_heat(self) -> dict[int, float]:
def solve_external_heat(self) -> dict[str, float]:
"""外部流体による熱交換量を求めます.
Returns:
Expand Down Expand Up @@ -93,71 +143,6 @@ def solve_external_heat(self) -> dict[int, float]:
for stream in updated_external_streams
}

@classmethod
def _lacking_heats(
cls,
temp_range_streams: defaultdict[TemperatureRange, set[Stream]]
) -> defaultdict[TemperatureRange, float]:
"""温度領域ごとの不足熱量を求めます.
Args:
temp_range_streams defaultdict[float, set[Stream]]:
温度領域ごとの流体のセット。
Returns:
defaultdict[TemperatureRange, float]: 温度領域ごとの過不足熱量。
"""
return defaultdict(int, {
temp_range: sum([s.heat() for s in streams if s.is_hot()]) - sum([s.heat() for s in streams if s.is_cold()])
for temp_range, streams in temp_range_streams.items()
})

@classmethod
def _get_heats(
cls,
temp_ranges: list[TemperatureRange],
temp_range_lacking_heat: dict[TemperatureRange, float]
) -> list[float]:
"""温度変化領域ごとの熱量変化を求めます。
Args:
temp_ranges: list[TemperatureRange]: 温度領域のリスト。
temp_range_lacking_heat: dict[TemperatureRange, float]:
温度領域ごとの過不足熱量。
Returns:
list[float]: 熱量のリスト。
"""
temp_ranges.sort()
heats = [0.0] * (len(temp_ranges) + 1)
for i, temp_range in enumerate(temp_ranges):
heats[i + 1] = heats[i] - temp_range_lacking_heat[temp_range]
min_heat = min(heats)

return [heat - min_heat for heat in heats]

def _set_pinch_point(self) -> tuple[float, int, float, int]:
"""ピンチポイントとピンチポイントのインデックスを求めます。
"""
# heat == 0は必ず存在する。
if 0 not in self.heats:
raise ValueError("heatに0が存在しません。")

pinch_point_indexes = [
i for i, heat in enumerate(self.heats) if heat == 0
]
pinch_points = [self.temps[i] for i in pinch_point_indexes]

if any(pinch_point_indexes) in [0, len(self.heats) - 1]:
print("ピンチポイントの値が不正である可能性があります。")

return (
pinch_points[-1],
pinch_point_indexes[-1],
pinch_points[0],
pinch_point_indexes[0]
)

def _update_external_streams(
self,
external_cold_streams: list[Stream],
Expand Down
Loading

0 comments on commit 6c29cc9

Please sign in to comment.