diff --git a/nifty6/field.py b/nifty6/field.py index 8d4d31970afa822cda43dda44b28e005b5c6e581..1e11768eedee0e615f94cf9370c5d762e8560e32 100644 --- a/nifty6/field.py +++ b/nifty6/field.py @@ -20,10 +20,10 @@ import numpy as np from . import utilities from .domain_tuple import DomainTuple -from .operators.operator import Operator +from .operand import Operand -class Field(Operator): +class Field(Operand): """The discrete representation of a continuous field over multiple spaces. Stores data arrays and carries all the needed meta-information (i.e. the diff --git a/nifty6/linearization.py b/nifty6/linearization.py index 9b84b86e9637217f859b82611272f4db9723d186..ee40973874f4a37997050831d634156d8dd2df6e 100644 --- a/nifty6/linearization.py +++ b/nifty6/linearization.py @@ -19,10 +19,10 @@ import numpy as np from .sugar import makeOp from . import utilities -from .operators.operator import Operator +from .operand import Operand -class Linearization(Operator): +class Linearization(Operand): """Let `A` be an operator and `x` a field. `Linearization` stores the value of the operator application (i.e. `A(x)`), the local Jacobian (i.e. `dA(x)/dx`) and, optionally, the local metric. diff --git a/nifty6/multi_field.py b/nifty6/multi_field.py index a05bd644ab88c84107bbf254bc7602464d0a0412..fc3005f8ab55620fc1f144d1ce0b457ecae4d154 100644 --- a/nifty6/multi_field.py +++ b/nifty6/multi_field.py @@ -21,10 +21,10 @@ from . import utilities from .field import Field from .multi_domain import MultiDomain from .domain_tuple import DomainTuple -from .operators.operator import Operator +from .operand import Operand -class MultiField(Operator): +class MultiField(Operand): def __init__(self, domain, val): """The discrete representation of a continuous field over a sum space. diff --git a/nifty6/operators/linear_operator.py b/nifty6/operators/linear_operator.py index 652c24d3192e16fce23430b626b6cbbaf43fe3ff..60f86cd0c50e81ed36408f5fcd782ad11282f6f1 100644 --- a/nifty6/operators/linear_operator.py +++ b/nifty6/operators/linear_operator.py @@ -169,8 +169,8 @@ class LinearOperator(Operator): raise NotImplementedError def __call__(self, x): - """Same as :meth:`times`""" - from ..linearization import Linearization + if isinstance(x, Operator): + return self @ x if x.jac is not None: return x.new(self(x.fld), self).prepend_jac(x.jac) if x.val is not None: diff --git a/nifty6/operators/operator.py b/nifty6/operators/operator.py index fa4e63501588df64471426108470cebd70926a80..0ff499691e40d27bb2116c03ad25444b48e5d92e 100644 --- a/nifty6/operators/operator.py +++ b/nifty6/operators/operator.py @@ -46,75 +46,6 @@ class Operator(metaclass=NiftyMeta): """ return self._target - @property - def fld(self): - """The field associated with this object - For "pure" operators this is `None`. For Field-like objects this - is a `Field` or a `MultiField` matching the object's `target`. - - Returns - ------- - None or Field or MultiField : the field object - """ - return None - - @property - def val(self): - """The numerical value associated with this object - For "pure" operators this is `None`. For Field-like objects this - is a `numpy.ndarray` or a dictionary of `numpy.ndarray`s matching the - object's `target`. - - Returns - ------- - None or numpy.ndarray or dictionary of np.ndarrays : the numerical value - """ - return None - - @property - def jac(self): - """The Jacobian associated with this object - For "pure" operators this is `None`. For Field-like objects this - can be `None` (in which case the object is a constant), or it can be a - `LinearOperator` with `domain` and `target` matching the object's. - - Returns - ------- - None or LinearOperator : the Jacobian - - Notes - ----- - if `value` is None, this must be `None` as well! - """ - return None - - @property - def want_metric(self): - """Whether a metric should be computed for the full expression. - This is `False` whenever `jac` is `None`. In other cases it signals - that operators processing this object should compute the metric. - - Returns - ------- - bool : whether the metric should be computed - """ - return False - - @property - def metric(self): - """The metric associated with the object. - This is `None`, except when all the following conditions hold: - - `want_metric` is `True` - - `target` is the scalar domain - - the operator chain contained an operator which could compute the - metric - - Returns - ------- - None or LinearOperator : the metric - """ - return None - @staticmethod def _check_domain_equality(dom_op, dom_field): if dom_op != dom_field: @@ -240,7 +171,8 @@ class Operator(metaclass=NiftyMeta): def _check_input(self, x): from .scaling_operator import ScalingOperator - if not (isinstance(x, Operator) and x.val is not None): + from ..operand import Operand + if not isinstance(x, Operand): raise TypeError if x.jac is not None: if not isinstance(x.jac, ScalingOperator): @@ -250,13 +182,14 @@ class Operator(metaclass=NiftyMeta): self._check_domain_equality(self._domain, x.domain) def __call__(self, x): - if not isinstance(x, Operator): + if isinstance(x, Operator): + return self @ x + from ..operand import Operand + if not isinstance(x, Operand): raise TypeError if x.jac is not None: return self.apply(x.trivial_jac()).prepend_jac(x.jac) - elif x.val is not None: - return self.apply(x) - return self @ x + return self.apply(x) def ducktape(self, name): from .simple_linear_operators import ducktape diff --git a/nifty6/operators/scaling_operator.py b/nifty6/operators/scaling_operator.py index b99d3380fa751f3f7bbfb8b15931efebd46ebad9..4706d42744ecb4e669ac2b0d7f8dcf173103b1ee 100644 --- a/nifty6/operators/scaling_operator.py +++ b/nifty6/operators/scaling_operator.py @@ -98,6 +98,9 @@ class ScalingOperator(EndomorphicOperator): def __call__(self, other): res = EndomorphicOperator.__call__(self, other) + from .operator import Operator + if isinstance(res, Operator): + return res if np.isreal(self._factor) and self._factor >= 0: if other.jac is not None: if other.metric is not None: