Source code for pypint.solutions.data_storage.step_solution_data

# coding=utf-8
"""

.. moduleauthor:: Torbjörn Klatt <[email protected]>
"""
from copy import deepcopy

import numpy as np

from pypint.solvers.diagnosis import Error, Residual
from pypint.utilities import assert_is_instance, assert_condition, class_name
from pypint.utilities.logging import LOG


[docs]class StepSolutionData(object): """Storage for the solution of a single time point. Finalization The attributes (:py:attr:`.value`, :py:attr:`.time_point`, :py:attr:`.error` and :py:attr:`.residual` can only be modified before calling :py:meth:`.finalize`. It is not intended and possible to *definalize* a once finalized :py:class:`StepSolutionData` instance. Comparability It can be compared with respect to all numerical comparison operators. For all operators to evaluate to :py:class:`True` it is necessary that :py:attr:`.dim` and :py:attr:`.numeric_type` are the same. Equality is given, if :py:attr:`.time_point`, :py:attr:`.error` and :py:attr:`.residual` are the same as well as :py:attr:`.value` with respect to :py:meth:`numpy.array_equal`. The other comparison operators do not take :py:attr:`.value`, :py:attr:`.error` and :py:attr:`.residual` into account and induce an order only with respect to :py:attr:`.time_point`. Hashable It is not hashable due to its wrapping around :py:class:`numpy.ndarray`. """
[docs] def __init__(self, *args, **kwargs): """ Parameters ---------- value : :py:class:`numpy.ndarray` Solution value. Size of the vector must equal the spacial dimension of the problem. time_point : :py:class:`float` Time point of associated with the solution. error : :py:class:`.Error` or :py:class:`numpy.ndarray` Error of the solution. residual : :py:class:`.Residual` or :py:class:`numpy.ndarray` Residual of the solution. Same abundance of constrains apply as for the error. Raises ------ ValueError : * if ``value`` is not a :py:class:`numpy.ndarray` * if ``time_point`` is not a :py:class:`float` * if either :py:attr:`.error` or :py:attr:`.residual` raises UserWarning : if no ``value`` or ``time_point`` is given Notes ----- The spacial dimension and the numerical type are derived from the given solution values. Thus, specifying :py:attr:`.ISolutionData.dim` and :py:attr:`.ISolutionData.numeric_type` is not recommended (in fact they are ignored). """ self._data = None self._time_point = None self._error = None self._residual = None self._dim = 0 self._numeric_type = None self._finalized = False if 'value' in kwargs: self.value = kwargs['value'] if 'time_point' in kwargs: self.time_point = kwargs['time_point'] if 'error' in kwargs: self.error = kwargs['error'] if 'residual' in kwargs: self.residual = kwargs['residual']
[docs] def finalize(self): """Locks this storage data instance. Raises ------ ValueError : If it has already been locked. """ assert_condition(not self.finalized, AttributeError, message="This solution data storage is already finalized.", checking_obj=self) self._finalized = True
def definalize(self): if self.finalized: self._finalized = False else: LOG.warning("This Solution is not finalized.") @property
[docs] def finalized(self): """Accessor for the lock state. Returns ------- finilized : :py:class:`bool` :py:class:`True` if it has been finalized before, :py:class:`False` otherwise """ return self._finalized
@property def value(self): """Accessor for the solution value. Returns ------- value : :py:class:`numpy.ndarray` Raises ------ ValueError : If this storage data instance has been finalized. *(only setter)* """ return self._data @value.setter
[docs] def value(self, value): assert_condition(not self.finalized, AttributeError, message="Cannot change this solution data storage any more.", checking_obj=self) assert_is_instance(value, np.ndarray, descriptor="Values", checking_obj=self) self._dim = value.shape self._numeric_type = value.dtype self._data = value
@property def time_point(self): """Accessor for the associated time point. Parameters ---------- time_point : :py:class:`float` Returns ------- time_point : :py:class:`float` Raises ------ ValueError : If this storage data instance has been finalized. *(only setter)* """ return self._time_point @time_point.setter
[docs] def time_point(self, time_point): assert_condition(not self.finalized, AttributeError, message="Cannot change this solution data storage any more.", checking_obj=self) assert_is_instance(time_point, float, descriptor="Time Point", checking_obj=self) self._time_point = time_point
@property def error(self): """Accessor for the error. Parameters ---------- error : :py:class:`.Error` or :py:class:`numpy.ndarray` Returns ------- error : :py:class:`.Error` or :py:class:`None` if no error is given Raises ------ ValueError : If this storage data instance has been finalized. *(only setter)* """ return self._error @error.setter
[docs] def error(self, error): assert_condition(not self.finalized, AttributeError, message="Cannot change this solution data storage any more.", checking_obj=self) assert_is_instance(error, (np.ndarray, Error), descriptor="Error", checking_obj=self) self._error = error if isinstance(error, Error) else Error(value=error)
@property def residual(self): """Accessor for the residual. Parameters ---------- residual : :py:class:`.Residual` or :py:class:`numpy.ndarray` Returns ------- residual : :py:class:`.Residual` or :py:class:`None` if no residual is given Raises ------ ValueError : If this storage data instance has been finalized. *(only setter)* """ return self._residual @residual.setter
[docs] def residual(self, residual): assert_condition(not self.finalized, AttributeError, message="Cannot change this solution data storage any more.", checking_obj=self) assert_is_instance(residual, (np.ndarray, Residual), descriptor="Residual", checking_obj=self) self._residual = residual if isinstance(residual, Residual) else Residual(value=residual)
@property
[docs] def dim(self): """Read-only accessor for the spacial dimension. Returns ------- dim : :py:class:`int` """ return self._dim
@property
[docs] def numeric_type(self): """Read-only accessor for the numerical type. Returns ------- numeric_type : :py:class:`numpy.dtype` """ return self._numeric_type
def __str__(self): return "StepSolutionData(value={}, time_point={}, finalized={})"\ .format(self.value, self.time_point, self.finalized) def __copy__(self): copy = self.__class__.__new__(self.__class__) copy.__dict__.update(self.__dict__) copy._finalized = False return copy def __deepcopy__(self, memo): copy = self.__class__.__new__(self.__class__) memo[id(self)] = copy for item, value in self.__dict__.items(): setattr(copy, item, deepcopy(value, memo)) copy._finalized = False return copy def __eq__(self, other): assert_is_instance(other, StepSolutionData, message="Can not compare StepSolutionData with {}".format(class_name(other)), checking_obj=self) return ( self.time_point == other.time_point and self.dim == other.dim and self.numeric_type == other.numeric_type and np.array_equal(self.value, other.value) and self.error == other.error and self.residual == other.residual ) def __ge__(self, other): assert_is_instance(other, StepSolutionData, message="Can not compare StepSolutionData with {}".format(class_name(other)), checking_obj=self) return ( self.dim == other.dim and self.numeric_type == other.numeric_type and self.time_point >= other.time_point ) def __gt__(self, other): assert_is_instance(other, StepSolutionData, message="Can not compare StepSolutionData with {}".format(class_name(other)), checking_obj=self) return ( self.dim == other.dim and self.numeric_type == other.numeric_type and self.time_point > other.time_point ) def __le__(self, other): assert_is_instance(other, StepSolutionData, message="Can not compare StepSolutionData with {}".format(class_name(other)), checking_obj=self) return ( self.dim == other.dim and self.numeric_type == other.numeric_type and self.time_point < other.time_point ) def __lt__(self, other): assert_is_instance(other, StepSolutionData, message="Can not compare StepSolutionData with {}".format(class_name(other)), checking_obj=self) return ( self.dim == other.dim and self.numeric_type == other.numeric_type and self.time_point < other.time_point ) def __ne__(self, other): assert_is_instance(other, StepSolutionData, message="Can not compare StepSolutionData with {}".format(class_name(other)), checking_obj=self) return not self.__eq__(other) # StepSolutionData is mutable __hash__ = None
__all__ = ['StepSolutionData']