Source code for pytanksim.core.simulationgenerator

# -*- coding: utf-8 -*-
"""Main module of pytanksim, used to generate simulations."""

# This file is a part of the python package pytanksim.
#
# Copyright (c) 2024 Muhammad Irfan Maulana Kusdhany, Kyushu University
#
# pytanksim is free software; you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

__all__ = ["generate_simulation", "automatic_simulation"]

from pytanksim.classes.basesimclass import BoundaryFlux, SimParams,\
    BaseSimulation
from pytanksim.classes.simresultsclass import SimResults
from pytanksim.classes.storagetankclasses import StorageTank, SorbentTank
from pytanksim.classes.onephasesorbentsimclasses import *
from pytanksim.classes.twophasesorbentsimclasses import *
from pytanksim.classes.onephasefluidsimclasses import *
from pytanksim.classes.twophasefluidsimclasses import *
from typing import Union

phase_to_str = {
    1: "One Phase",
    2: "Two Phase"
    }

sim_class_dict = {
    "One Phase Sorbent Default": OnePhaseSorbentDefault,
    "One Phase Sorbent Venting": OnePhaseSorbentVenting,
    "One Phase Sorbent Cooled": OnePhaseSorbentCooled,
    "One Phase Sorbent Heated": OnePhaseSorbentHeatedDischarge,
    "Two Phase Sorbent Default": TwoPhaseSorbentDefault,
    "Two Phase Sorbent Venting": TwoPhaseSorbentVenting,
    "Two Phase Sorbent Cooled": TwoPhaseSorbentCooled,
    "Two Phase Sorbent Heated": TwoPhaseSorbentHeatedDischarge,
    "One Phase Fluid Default": OnePhaseFluidDefault,
    "One Phase Fluid Venting": OnePhaseFluidVenting,
    "One Phase Fluid Cooled": OnePhaseFluidCooled,
    "One Phase Fluid Heated": OnePhaseFluidHeatedDischarge,
    "Two Phase Fluid Default": TwoPhaseFluidDefault,
    "Two Phase Fluid Venting": TwoPhaseFluidVenting,
    "Two Phase Fluid Cooled": TwoPhaseFluidCooled,
    "Two Phase Fluid Heated": TwoPhaseFluidHeatedDischarge
    }


[docs]def generate_simulation( storage_tank: Union[StorageTank, SorbentTank], boundary_flux: BoundaryFlux, simulation_params: SimParams, simulation_type: str = "Default", phase: int = 1 ) -> BaseSimulation: """Generate a dynamic simulation object. Parameters ---------- storage_tank : Union[StorageTank, SorbentTank] An object with the properties of the storage tank. Can either be of the class StorageTank or its child class SorbentTank. boundary_flux : BoundaryFlux An object containing information about the mass and energy entering and leaving the control volume of the tank. simulation_params : SimParams An object containing various parameters for the dynamic simulation. simulation_type : str, optional A string describing the type of the simulation to be run. The default is "Default". The valid types are: - ``Default`` : A regular dynamic simulation with no constraints. - ``Cooled`` : A simulation where the tank is cooled to maintain a constant pressure. Here, the cooling power becomes one of the output variables. Typically used for simulating refueling after the tank has reached maximum allowable working pressure, or for simulating zero boil-off systems which are actively cooled. - ``Heated``: A simulation where the tank is heated to maintain a constant pressure. Here, the heating power becomes one of the output variables. Typically used for simulating discharging when the tank has reached the minimum supply pressure of the fuel cell system. - ``Venting`` : A simulation where the tank vents the fluid stored inside to maintain a constant pressure. Here, the amount vented becomes an output variable. Typically used to simulate boil-off or refueling with a feed-and-bleed scheme. phase : int, optional Specifies whether the fluid being stored is a single phase (1) or a two-phase (2) liquid and gas mixture. The default is 1 for single phase. Returns ------- A child class of BaseSimulation A simulation object which can be ``run()`` to output a SimResults object. Which class will be generated depends on the parameters provided to this function. """ if isinstance(storage_tank, SorbentTank): hasSorbent = " Sorbent " else: hasSorbent = " Fluid " class_caller = phase_to_str[phase] + hasSorbent + simulation_type return sim_class_dict.\ get(class_caller)(storage_tank=storage_tank, boundary_flux=boundary_flux, simulation_params=simulation_params)
def _gen_phase(res: SimResults, prev_phase: int) -> int: """ Generate number of phases for the next simulation in automated simulations. Parameters ---------- res : SimResults Results of the previous simulation. prev_phase : int The number of fluid phases in the previous simulation. If the fluid was a single phase, it's 1. If the fluid was on the saturation line and there was a vapor-liquid equilibrium, then it's 2. Returns ------- int Number of fluid phases in the next simulation. """ if prev_phase == 1: phase = 2 if res.stop_reason == "SaturLineReached" else 1 else: phase = 1 if res.stop_reason == "PhaseChangeEnded" else 2 return phase def _gen_type(res: SimResults, handle_max_pres: str, handle_min_pres: str) -> str: """ Generate the next simulation type in a series of automated simulations. Parameters ---------- res : SimResults Results of the previous simulation. handle_max_pres : str A string indicating how the simulation is to continue if the tank has reached its maximum allowable working pressure. "Cooled" means that the tank will not vent any gas, but will be actively cooled down. "Venting" means that the tank will begin to vent the exact amount of fluid inside to maintain the maximum pressure. handle_min_pres : str A string indicating how the simulation is to continue if the tank has reached its minimum supply pressure. "Heated" means exactly enough heat will be provided to the tank to maintain the minimum supply pressure. "Continue" means the simulation will restart without changing any parameters. Returns ------- str The simulation type. """ if res.stop_reason == "MaxPresReached": return handle_max_pres elif res.stop_reason == "MinPresReached": if handle_min_pres == "Continue": return "Default" else: return handle_min_pres else: return "Default"
[docs]def automatic_simulation( storage_tank: Union[StorageTank, SorbentTank], boundary_flux: BoundaryFlux, simulation_params: SimParams, stop_at_max_pres: bool = False, stop_at_min_pres: bool = False, handle_max_pres: str = "Cooled", handle_min_pres: str = "Heated") -> SimResults: """ Automatically run and restart simulations until a target is reached. Parameters ---------- storage_tank : Union[StorageTank, SorbentTank] An object with the properties of the storage tank. Can either be of the class StorageTank or its child class SorbentTank. boundary_flux : BoundaryFlux An object containing information about the mass and energy entering and leaving the control volume of the tank. simulation_params : SimParams An object containing various parameters for the dynamic simulation. stop_at_max_pres : bool, optional Whether or not the simulation is to be stopped when the tank hits its maximum allowable working pressure. The default is False. stop_at_min_pres : bool, optional Whether or not the simulation is to be stopped when the tank hits its minimum supply pressure. The default is False. handle_max_pres : str, optional A string indicating how the simulation is to continue if the tank has reached its maximum allowable working pressure. "Cooled" means that the tank will not vent any gas, but will be actively cooled down. "Venting" means that the tank will begin to vent the exact amount of fluid inside to maintain the maximum pressure. The default is "Cooled". handle_min_pres : str, optional A string indicating how the simulation is to continue if the tank has reached its minimum supply pressure. "Heated" means exactly enough heat will be provided to the tank to maintain the minimum supply pressure. "Continue" means the simulation will restart without changing any parameters. The default is "Heated". Returns ------- SimResults An object for storing and manipulating the results of the dynamic simulations. """ spr = simulation_params init_p = spr.init_pressure init_T = spr.init_temperature init_phase = storage_tank.\ stored_fluid.determine_phase(init_p, init_T) valid_stop_reasons = ["FinishedNormally", "TargetTempReached", "TargetPresReached", "TargetCondsReached", "TargetCapReached", "CritPointReached"] if stop_at_max_pres: valid_stop_reasons.append("MaxPresReached") if stop_at_min_pres: valid_stop_reasons.append("MinPresReached") res_list = [] simtype = "Default" phase = 1 if init_phase != "Saturated" else 2 sim = generate_simulation(storage_tank, boundary_flux, spr, phase=phase, simulation_type=simtype) res = sim.run() res_list.append(res) while not (res.stop_reason in valid_stop_reasons): phase = _gen_phase(res, phase) simtype = _gen_type(res, handle_max_pres, handle_min_pres) spr = SimParams.from_SimResults(res) sim = generate_simulation(storage_tank, boundary_flux, spr, phase=phase, simulation_type=simtype) res = sim.run() res_list.append(res) return SimResults.combine(res_list)