Source code for wntr.msx.options

# coding: utf-8
"""
The wntr.msx.options module includes options for multi-species water quality
models
"""

import logging
from typing import Dict, List, Literal, Union

from wntr.network.options import _OptionsBase

logger = logging.getLogger(__name__)


[docs] class MsxReportOptions(_OptionsBase): """ Report options Parameters ---------- report_filename : str Filename for the EPANET-MSX report file, by default this will be the prefix plus ".rpt". species : dict[str, bool] Output species concentrations species_precision : dict[str, float] Output species concentrations with the specified precision nodes : None, "ALL", or list Output node information. If a list of node names is provided, EPANET-MSX only provides report information for those nodes. links : None, "ALL", or list Output link information. If a list of link names is provided, EPANET-MSX only provides report information for those links. pagesize : str Page size for EPANET-MSX report output """
[docs] def __init__( self, pagesize: list = None, report_filename: str = None, species: Dict[str, bool] = None, species_precision: Dict[str, float] = None, nodes: Union[Literal["ALL"], List[str]] = None, links: Union[Literal["ALL"], List[str]] = None, ): self.pagesize = pagesize """Pagesize for the report""" self.report_filename = report_filename """Prefix of the report filename (will add .rpt)""" self.species = species if species is not None else dict() """Turn individual species outputs on and off, by default no species are output""" self.species_precision = species_precision if species_precision is not None else dict() """Output precision for the concentration of a specific species""" self.nodes = nodes """List of nodes to print output for, or 'ALL' for all nodes, by default None""" self.links = links """List of links to print output for, or 'ALL' for all links, by default None"""
def __setattr__(self, name, value): if name not in ["pagesize", "report_filename", "species", "nodes", "links", "species_precision"]: raise AttributeError("%s is not a valid attribute of ReportOptions" % name) self.__dict__[name] = value
[docs] class MsxSolverOptions(_OptionsBase): """ Solver options Parameters ---------- timestep : int >= 1 Water quality timestep (seconds), by default 60 (one minute). area_units : str, optional Units of area to use in surface concentration forms, by default ``M2``. Valid values are ``FT2``, ``M2``, or ``CM2``. rate_units : str, optional Time units to use in all rate reactions, by default ``MIN``. Valid values are ``SEC``, ``MIN``, ``HR``, or ``DAY``. solver : str, optional Solver to use, by default ``RK5``. Options are ``RK5`` (5th order Runge-Kutta method), ``ROS2`` (2nd order Rosenbrock method), or ``EUL`` (Euler method). coupling : str, optional Use coupling method for solution, by default ``NONE``. Valid options are ``FULL`` or ``NONE``. atol : float, optional Absolute concentration tolerance, by default 0.01 (regardless of species concentration units). rtol : float, optional Relative concentration tolerance, by default 0.001 (±0.1%). compiler : str, optional Whether to use a compiler, by default ``NONE``. Valid options are ``VC``, ``GC``, or ``NONE`` segments : int, optional Maximum number of segments per pipe (MSX 2.0 or newer only), by default 5000. peclet : int, optional Peclet threshold for applying dispersion (MSX 2.0 or newer only), by default 1000. report : MsxReportOptions or dict Options on how to report out results. """
[docs] def __init__( self, timestep: int = 360, area_units: str = "M2", rate_units: str = "MIN", solver: str = "RK5", coupling: str = "NONE", atol: float = 1.0e-4, rtol: float = 1.0e-4, compiler: str = "NONE", segments: int = 5000, peclet: int = 1000, # global_initial_quality: Dict[str, float] = None, report: MsxReportOptions = None, ): self.timestep: int = timestep """Timestep, in seconds, by default 360""" self.area_units: str = area_units """Units used to express pipe wall surface area where, by default FT2. Valid values are FT2, M2, and CM2.""" self.rate_units: str = rate_units """Units in which all reaction rate terms are expressed, by default HR. Valid values are HR, MIN, SEC, and DAY.""" self.solver: str = solver """Solver to use, by default EUL. Valid values are EUL, RK5, and ROS2.""" self.coupling: str = coupling """Whether coupling should occur during solving, by default NONE. Valid values are NONE and FULL.""" self.rtol: float = rtol """Relative tolerance used during solvers ROS2 and RK5, by default 0.001 for all species. Can be overridden on a per-species basis.""" self.atol: float = atol """Absolute tolerance used by the solvers, by default 0.01 for all species regardless of concentration units. Can be overridden on a per-species basis.""" self.compiler: str = compiler """Compiler to use if the equations should be compiled by EPANET-MSX, by default NONE. Valid options are VC, GC and NONE.""" self.segments: int = segments """Number of segments per-pipe to use, by default 5000.""" self.peclet: int = peclet """Threshold for applying dispersion, by default 1000.""" self.report: MsxReportOptions = MsxReportOptions.factory(report) """Reporting output options."""
def __setattr__(self, name, value): if name == "report": if not isinstance(value, (MsxReportOptions, dict, tuple, list)): raise ValueError("report must be a ReportOptions or convertable object") value = MsxReportOptions.factory(value) elif name in {"timestep"}: try: value = max(1, int(value)) except ValueError: raise ValueError("%s must be an integer >= 1" % name) elif name in ["atol", "rtol"]: try: value = float(value) except ValueError: raise ValueError("%s must be a number", name) elif name in ["segments", "peclet"]: try: value = int(value) except ValueError: raise ValueError("%s must be a number", name) elif name not in ["area_units", "rate_units", "solver", "coupling", "compiler"]: raise ValueError("%s is not a valid member of MsxSolverOptions") self.__dict__[name] = value
[docs] def to_dict(self): """Dictionary representation of the options""" return dict(self)