Source code for pycomus.ComusDis.CmsTime

# --------------------------------------------------------------
# CmsTime.py
# Version: 1.0.0
# Author: Zhenjiang Wu
# Description: Set COMUS Model Stress Period Attributes.
# --------------------------------------------------------------
import os
from typing import List, Tuple, Union

from pycomus.Utils.CONSTANTS import PERIOD_FILE_NAME, PERIOD_PKG_NAME


[docs] class ComusPeriod: """ Set COMUS Model Period Attributes. Attributes: ---------------------------- model: pycomus.ComusModel COMUS Model Object. period: Union[Tuple, List[Tuple]] It can be a Tuple or a List[Tuple], and each Tuple should contain three elements, which are PERLEN, NSTEP and MULTR, and each element should be greater than 0. Methods: -------- __init__(self, model, period: Union[Tuple, List[Tuple]]) Set COMUS Model Period Attributes. load(cls, model, period_file: str) Load parameters from a PerAttr.in file and create a ComusPeriod instance. write_file(self, folder_path: str) Typically used as an internal function but can also be called directly, it outputs the `pycomus.ComusPeriod` module to the specified path as <PerAttr.in>. Returns: -------- controlParams: pycomus.ComusPeriod COMUS Period Attributes Object. Example: -------- >>> import pycomus >>> model1 = pycomus.ComusModel(model_name="test") >>> period1 = pycomus.ComusPeriod(model1, [(1, 1, 1)]) """ def __init__(self, model, period: Union[Tuple, List[Tuple]]): self.period: Union[Tuple, List[Tuple]] = self._validate_period(period) self._model = model model.package[PERIOD_PKG_NAME] = self @staticmethod def _validate_period(period: Union[Tuple, List[Tuple]]) -> Union[Tuple, List[Tuple]]: if isinstance(period, tuple): if len(period) == 3 and all(isinstance(val, (int, float)) and val > 0 for val in period): return [period] else: raise ValueError("Invalid period format. The tuple should have 3 numeric values, all greater than 0.") elif isinstance(period, list): if all(isinstance(t, tuple) and len(t) == 3 and all(isinstance(val, (int, float)) and val > 0 for val in t) for t in period): return period else: raise ValueError( "Invalid period format. Each tuple should have 3 numeric values, and all values should be greater than 0.") else: raise ValueError("Invalid period format. 'period' should be a tuple or a list of tuples.")
[docs] @classmethod def load(cls, model, period_file: str): """ Load parameters from a PerAttr.in file and create a ComusPeriod instance. Parameters: -------- model: pycomus.ComusModel COMUS Model Object. period_file: str Period Params file path. Returns: -------- instance: pycomus.ComusPeriod COMUS Period Params Object. Example: -------- >>> import pycomus >>> model1 = pycomus.ComusModel(model_name="test") >>> modelPeriod = pycomus.ComusPeriod.load(model1,"./InputFiles/PerAttr.in") """ with open(period_file, 'r') as file: lines: List[str] = file.readlines()[1:] if len(lines[0].strip().split()) != 4: raise ValueError("The Control Params file header should have 30 fields.") idx_list: List[int] = [int(line.strip().split()[0]) for line in lines] if sorted(idx_list) != [i for i in range(1, len(idx_list) + 1)]: raise ValueError(f"Period id should start from 1 and continue consecutively to {len(idx_list) + 1}.") period = [] for line in lines: line = line.strip().split() period.append((float(line[1]), float(line[2]), float(line[3]))) instance = cls(model, period) return instance
def __str__(self) -> str: return "IPER PERLEN NSTEP MULTR\n" + "\n".join( [f"{i + 1} {' '.join(map(str, tpl))}" for i, tpl in enumerate(self.period)]) + "\n" def __len__(self) -> int: return len(self.period) def __getitem__(self, item): if isinstance(item, slice): return self.period[item] elif isinstance(item, int) and 0 <= item < len(self.period): return self.period[item] else: raise IndexError("Index out of range") def __add__(self, other): if isinstance(other, ComusPeriod) and self._model is other._model: return ComusPeriod(self._model, self.period + other.period) else: raise TypeError("Can only concatenate with another ComusPeriod of the same model.")
[docs] def write_file(self, folder_path: str): """ Typically used as an internal function but can also be called directly, it outputs the `pycomus.ComusPeriod` module to the specified path as <PerAttr.in>. :param folder_path: Output folder path. """ with open(os.path.join(folder_path, PERIOD_FILE_NAME), "w") as file: file.write("IPER PERLEN NSTEP MULTR\n") index = 1 for value in self.period: file.write(f"{int(index)} {float(value[0])} {int(value[1])} {float(value[2])} \n") index += 1