Source code for fridom.framework.exceptions

"""exceptions.py - Custom exceptions for the framework."""
from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    import fridom.framework as fr


[docs] class TooManyArgumentsError(Exception): """Raise when too many arguments are provided.""" def __init__(self, max_args: int, **provided_args: any) -> None: message = ( "Too many arguments provided. " f"Expected at most {max_args}, got {len(provided_args)}: " f"{provided_args}." ) super().__init__(message )
[docs] @staticmethod def check(max_args: int, **provided_args: any) -> None: """Check if the number of provided arguments is correct.""" if sum(arg is not None for arg in provided_args.values()) > max_args: raise TooManyArgumentsError(max_args, **provided_args)
[docs] class PartialDomainError(NotImplementedError): """ Raise when an operation is attempted on a field that is not fully extended. Description ----------- Fields in the computational framework are marked with a `topo` attribute, which is a tuple of booleans indicating whether the field is extended in each spatial direction. For example, a field with `topo=(True, True, False)` depends on `x` and `y`, but not on `z`. Certain operations require the field to be fully extended in all directions (i.e., `topo=(True, True, True)`). If an unsupported operation is attempted on a field that is not fully extended, this exception is raised. """ def __init__(self, topo: tuple[bool]) -> None: super().__init__( f"Operation not available for fields with topo={topo}. " "Fields must be fully extended in all directions.")
[docs] @staticmethod def check(field: fr.ScalarField) -> None: """ Check if the given field is fully extended. Parameters ---------- field : fr.ScalarField The field to check. Raises ------ PartialDomainError: If `topo` is not fully extended. """ if not all(field.topo): raise PartialDomainError(field.topo)
[docs] class FieldSpaceError(NotImplementedError): """ Raise when attempting to perform an operation on a field in the wrong space. Description ----------- Fields in the computational framework have an `is_spectral` attribute, which is a boolean indicating whether the field is in spectral space. Certain operations require the field to be either in spectral space (`is_spectral=True`) or physical space (`is_spectral=False`). If an unsupported operation is attempted on a field in the wrong state, this exception is raised. Parameters ---------- is_spectral : bool The is_spectral attribute of the field. """ def __init__(self, is_spectral: bool) -> None: # noqa: FBT001 self.is_spectral = is_spectral state = "spectral" if is_spectral else "physical" super().__init__( f"Operation not available for fields in {state} space. " "Ensure the field is in the correct space for the operation.")
[docs] @staticmethod def check_if_spectral(field: fr.FieldBase) -> None: """ Check if the given field is in spectral space. Parameters ---------- field : fr.FieldBase The field to check. Raises ------ FieldSpaceError: If `is_spectral` is False. """ if not field.is_spectral: raise FieldSpaceError(field.is_spectral)
[docs] @staticmethod def check_if_physical(field: fr.FieldBase) -> None: """ Check if the given field is in physical space. Parameters ---------- field : fr.FieldBase The field to check. Raises ------ FieldSpaceError: If `is_spectral` is True. """ if field.is_spectral: raise FieldSpaceError(field.is_spectral)
[docs] class NotSetUpError(AttributeError): """Raise when an operation is attempted before the module is set up.""" def __init__(self, module_name: str, attribute: str) -> None: msg = f"Trying to access attribute '{attribute}' of '{module_name}'." msg += " But the module is not set up yet.\n" msg += " Call the 'setup' method first." super().__init__(msg)
[docs] @staticmethod def check(instance: fr.modules.Module | fr.grid.GridBase, attribute: str) -> None: """ Check if the module or grid is set up. Parameters ---------- instance : Module | GridBase The instance to check. attribute : str The attribute being accessed. """ if not instance.is_setup: # get the class name of the instance cls_name = instance.__class__.__name__ raise NotSetUpError(cls_name, attribute)