Source code for z2pack._control

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Abstract base classes for Control objects, which govern the iteration of Z2Pack runs."""

import abc
import types

from fsc.export import export


[docs]@export class ControlContainer(types.SimpleNamespace): """ Container for controls, giving simple access to the different types of controls. """ def __init__(self, *, controls, categories, valid_type): # pylint: disable=missing-function-docstring self.all = controls for ctrl in self.all: if not isinstance(ctrl, valid_type): raise ValueError( "Invalid type '{}' of control, should be '{}'.".format( type(ctrl), valid_type ) ) for name, ctrl_types in categories.items(): setattr( self, name, [ ctrl for ctrl in controls if all(isinstance(ctrl, ctrl_t) for ctrl_t in ctrl_types) ] )
[docs]@export class AbstractControl(metaclass=abc.ABCMeta): """ABC for all control objects. Instances must also have a 'state' attribute to work correctly, which is not enforced by the ABC."""
[docs]@export class StatefulControl(AbstractControl): """ ABC for control objects which have a state. The state must not depend on the given convergence parameters. **Concepts:** `Constructor:` ``StatefulControl(state=s).state == s`` for any valid state s. `State:` The state must be sufficient to uniquely determine the behaviour of the Control, for a given set of input parameters of the constructor. That is, given two equivalent StatefulControl objects, when applying .. code :: python sc1 = StatefulControl(*args, **kwargs) sc2 = StatefulControl(*args, **kwargs) ...working with sc1 and/or sc2... sc2.state = sc1.state ``sc1`` and ``sc2`` are again equivalent. In particular, it is not necessary to use ``update()`` on ``sc2`` in the case of a DataControl. """ @abc.abstractmethod def __init__(self, *, state=None, **kwargs): super().__init__(**kwargs) @property @abc.abstractmethod def state(self): """Returns the state of the Control.""" @state.setter @abc.abstractmethod def state(self, value): """Sets the state of the Control."""
[docs]@export class DataControl(AbstractControl): """ABC for control objects which can be updated with data.""" @abc.abstractmethod def update(self, data): pass
[docs]@export class IterationControl(AbstractControl): """ABC for iteration control objects. Enforces the existence of ...""" @abc.abstractmethod def __next__(self): pass
[docs]@export class ConvergenceControl(AbstractControl): """ABC for convergence tester objects. Enforces the existence of an update method, and the ``converged`` property. For LineControl objects, the converged property must be valid (False) also before the first update() call. This is not required for SurfaceControl objects.""" @property @abc.abstractmethod def converged(self): pass
# The only purpose of these subclasses is to distinguish between # ConvergenceControls which take a VolumeData, SurfaceData or LineData object.
[docs]@export class VolumeControl(AbstractControl): """Specializes AbstractControl for Volume objects"""
[docs]@export class SurfaceControl(AbstractControl): """Specializes AbstractControl for Surface objects"""
[docs]@export class LineControl(AbstractControl): """Specializes AbstractControl for Line objects"""