Skip to content

Commit

Permalink
Custom Higher Level Exceptions (#2176)
Browse files Browse the repository at this point in the history
* Custom Higher Level Exceptions

* Remove dunder method overload

* Remove exceptions from __init__

* Move excpetions to top

* Doc fix

* Add docstring

* Update tests

* Add more exceptions

* Add new tests

* Add new test execution

* field data

* test fix

* test fix 2

* redesign 1

* redesign 2

* redesign 3

* doc fix

* update 1

* update 2

* update 3

* update 4

* update 5

* update 6

* test fix

* test fix error_message

* correct a typo

* Updated error messages

* Incorporate TaskObject change

* Incorporate TaskObject change 2

* Incorporate TaskObject change 3

* Incorporate TaskObject change 4

* Update test
  • Loading branch information
hpohekar authored Nov 13, 2023
1 parent 5c81a34 commit 19f57f7
Show file tree
Hide file tree
Showing 29 changed files with 511 additions and 323 deletions.
35 changes: 35 additions & 0 deletions src/ansys/fluent/core/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""Custom common higher level exceptions."""

from typing import Any, Optional

from ansys.fluent.core.solver.error_message import allowed_name_error_message


class DisallowedValuesError(ValueError):
"""Provides the error when an argument value is not in allowed values."""

def __init__(
self,
context: Optional[Any] = None,
name: Optional[Any] = None,
allowed_values: Optional[Any] = None,
):
super().__init__(
allowed_name_error_message(
context=context, trial_name=name, allowed_values=allowed_values
)
)


class InvalidArgument(ValueError):
"""Provides the error when an argument value is inappropriate."""

pass


class SurfaceSpecificationError(ValueError):
"""Provides the error when both ``surface_ids`` and ``surface_names`` are
provided."""

def __init__(self):
super().__init__("Provide either 'surface_ids' or 'surface_names'.")
89 changes: 44 additions & 45 deletions src/ansys/fluent/core/file_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import numpy as np

from ansys.api.fluent.v0.field_data_pb2 import DataLocation
from ansys.fluent.core.exceptions import SurfaceSpecificationError
from ansys.fluent.core.filereader.case_file import CaseFile
from ansys.fluent.core.filereader.data_file import DataFile
from ansys.fluent.core.services.field_data import (
Expand All @@ -14,6 +15,20 @@
)


class InvalidMultiPhaseFieldName(ValueError):
"""Provides the error when multi-phase field name is inappropriate."""

def __init__(self):
super().__init__("Multi-phase field name should start with 'phase-'.")


class InvalidFieldName(ValueError):
"""Provides the error when a field name is inappropriate."""

def __init__(self):
super().__init__("The only allowed field is 'velocity'.")


class Transaction:
"""Populates field data on surfaces."""

Expand Down Expand Up @@ -108,15 +123,15 @@ def add_scalar_fields_request(
Raises
------
RuntimeError
If surface names or surface ids are not provided.
RuntimeError
SurfaceSpecificationError
If both ``surface_ids`` and ``surface_names`` are provided.
InvalidMultiPhaseFieldName
If field name does not have prefix ``phase-`` for multi-phase cases.
"""
if surface_ids is None:
surface_ids = []
if surface_ids and surface_names:
raise RuntimeError("Please provide either surface names or surface ids.")
raise SurfaceSpecificationError()

if surface_names:
for surface_name in surface_names:
Expand All @@ -126,9 +141,7 @@ def add_scalar_fields_request(

if len(self._file_session._data_file.get_phases()) > 1:
if not field_name.startswith("phase-"):
raise RuntimeError(
"For multi-phase cases field name should have a prefix of phase name."
)
raise InvalidMultiPhaseFieldName()
self._scalar_field_transactions.append(
Transaction._ScalarFieldTransaction(
field_name, surface_ids, field_name.split(":")[0]
Expand Down Expand Up @@ -162,15 +175,15 @@ def add_vector_fields_request(
Raises
------
RuntimeError
If surface names or surface ids are not provided.
RuntimeError
SurfaceSpecificationError
If both ``surface_ids`` and ``surface_names`` are provided.
InvalidMultiPhaseFieldName
If field name does not have prefix ``phase-`` for multi-phase cases.
"""
if surface_ids is None:
surface_ids = []
if surface_ids and surface_names:
raise RuntimeError("Please provide either surface names or surface ids.")
raise SurfaceSpecificationError()

if surface_names:
for surface_name in surface_names:
Expand All @@ -180,9 +193,7 @@ def add_vector_fields_request(

if len(self._file_session._data_file.get_phases()) > 1:
if not field_name.startswith("phase-"):
raise RuntimeError(
"For multi-phase cases field name should have a prefix of phase name."
)
raise InvalidMultiPhaseFieldName()
self._vector_field_transactions.append(
Transaction._VectorFieldTransaction(
field_name, surface_ids, field_name.split(":")[0]
Expand Down Expand Up @@ -227,7 +238,7 @@ def get_fields(self):
Raises
------
RuntimeError
InvalidFieldName
If any field other than ``"velocity"`` is provided.
"""
mesh = self._file_session._case_file.get_mesh()
Expand Down Expand Up @@ -258,7 +269,7 @@ def get_fields(self):

for transaction in self._vector_field_transactions:
if "velocity" not in transaction.field_name:
raise RuntimeError("Only 'velocity' is allowed field.")
raise InvalidFieldName()
if vector_field_tag not in field_data:
field_data[vector_field_tag] = {}
field_data_surface = field_data[vector_field_tag]
Expand Down Expand Up @@ -323,11 +334,11 @@ def get_surface_data(
Raises
------
RuntimeError
If surface names or surface ids are not provided.
SurfaceSpecificationError
If both ``surface_ids`` and ``surface_names`` are provided.
"""
if surface_ids and surface_name:
raise RuntimeError("Please provide either surface name or surface ids.")
raise SurfaceSpecificationError()

if data_type == SurfaceDataType.Vertices:
if surface_name:
Expand Down Expand Up @@ -407,25 +418,21 @@ def get_scalar_field_data(
Raises
------
RuntimeError
If surface names or surface ids are not provided.
RuntimeError
If field name does not have prefix ``phase-`` for multi-phase cases.
RuntimeError
SurfaceSpecificationError
If both ``surface_ids`` and ``surface_names`` are provided.
InvalidMultiPhaseFieldName
If field name does not have prefix ``phase-`` for multi-phase cases.
"""
if surface_ids and surface_name:
raise RuntimeError("Please provide either surface name or surface ids.")
raise SurfaceSpecificationError()

if surface_name:
surface_ids = self._field_info.get_surfaces_info()[surface_name][
"surface_id"
]
if len(self._file_session._data_file.get_phases()) > 1:
if not field_name.startswith("phase-"):
raise RuntimeError(
"For multi-phase cases field name should have a prefix of phase name."
)
raise InvalidMultiPhaseFieldName()
return ScalarFieldData(
surface_ids[0],
self._file_session._data_file.get_face_scalar_field_data(
Expand All @@ -444,9 +451,7 @@ def get_scalar_field_data(
else:
if len(self._file_session._data_file.get_phases()) > 1:
if not field_name.startswith("phase-"):
raise RuntimeError(
"For multi-phase cases field name should have a prefix of phase name."
)
raise InvalidMultiPhaseFieldName()
return {
surface_id: ScalarFieldData(
surface_id,
Expand Down Expand Up @@ -495,33 +500,29 @@ def get_vector_field_data(
Raises
------
RuntimeError
If surface names or surface ids are not provided.
RuntimeError
SurfaceSpecificationError
If both ``surface_ids`` and ``surface_names`` are provided.
InvalidFieldName
If any field other than ``"velocity"`` is provided.
RuntimeError
If field name does not have prefix ``phase-`` for multi-phase cases.
RuntimeError
InvalidMultiPhaseFieldName
If field name does not have prefix ``phase-`` for multi-phase cases.
"""
if surface_ids and surface_name:
raise RuntimeError("Please provide either surface name or surface ids.")
raise SurfaceSpecificationError()

if (
field_name.lower() != "velocity"
and field_name.split(":")[1].lower() != "velocity"
):
raise RuntimeError("Only 'velocity' is allowed field.")
raise InvalidFieldName()

if surface_name:
surface_ids = self._field_info.get_surfaces_info()[surface_name][
"surface_id"
]
if len(self._file_session._data_file.get_phases()) > 1:
if not field_name.startswith("phase-"):
raise RuntimeError(
"For multi-phase cases field name should have a prefix of phase name."
)
raise InvalidMultiPhaseFieldName()
vector_data = self._file_session._data_file.get_face_vector_field_data(
field_name.split(":")[0], surface_ids[0]
)
Expand All @@ -534,9 +535,7 @@ def get_vector_field_data(
else:
if len(self._file_session._data_file.get_phases()) > 1:
if not field_name.startswith("phase-"):
raise RuntimeError(
"For multi-phase cases field name should have a prefix of phase name."
)
raise InvalidMultiPhaseFieldName()
return {
surface_id: VectorFieldData(
surface_id,
Expand Down
43 changes: 34 additions & 9 deletions src/ansys/fluent/core/fluent_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,30 @@
logger = logging.getLogger("pyfluent.general")


class PortNotProvided(ValueError):
"""Provides the error when port is not provided."""

def __init__(self):
super().__init__(
"Provide the 'port' to connect to an existing Fluent instance."
)


class UnsupportedRemoteFluentInstance(ValueError):
"""Provides the error when 'wait_process_finished' does not support remote Fluent
session."""

def __init__(self):
super().__init__("Remote Fluent instance is unsupported.")


class WaitTypeError(TypeError):
"""Provides the error when invalid ``wait`` type is provided."""

def __init__(self):
super().__init__("Invalid 'wait' type.")


def _get_max_c_int_limit() -> int:
"""Get the maximum limit of a C int.
Expand Down Expand Up @@ -236,6 +260,11 @@ def __init__(
inside_container: bool, optional
Whether the Fluent session that is being connected to
is running inside a docker container.
Raises
------
PortNotProvided
If port is not provided.
"""
self.error_state = ErrorState()
self._data_valid = False
Expand All @@ -250,9 +279,7 @@ def __init__(
port = os.getenv("PYFLUENT_FLUENT_PORT")
self._channel_str = f"{ip}:{port}"
if not port:
raise ValueError(
"The port to connect to Fluent session is not provided."
)
raise PortNotProvided()
# Same maximum message length is used in the server
max_message_length = _get_max_c_int_limit()
self._channel = grpc.insecure_channel(
Expand Down Expand Up @@ -495,15 +522,13 @@ def wait_process_finished(self, wait: Union[float, int, bool] = 60):
Raises
------
ValueError
UnsupportedRemoteFluentInstance
If current Fluent instance is running remotely.
TypeError
WaitTypeError
If ``wait`` is specified improperly.
"""
if self._remote_instance:
raise ValueError(
"Fluent remote instance not supported by FluentConnection.wait_process_finished()."
)
raise UnsupportedRemoteFluentInstance()
if isinstance(wait, bool):
if wait:
wait = 60
Expand All @@ -513,7 +538,7 @@ def wait_process_finished(self, wait: Union[float, int, bool] = 60):
if isinstance(wait, (float, int)):
logger.info(f"Waiting {wait} seconds for Fluent processes to finish...")
else:
raise TypeError("Invalid 'limit' type.")
raise WaitTypeError()
if self.connection_properties.inside_container:
_response = timeout_loop(
get_container,
Expand Down
Loading

0 comments on commit 19f57f7

Please sign in to comment.