# This file was automatically generated by SWIG (https://www.swig.org).
# Version 4.1.1
#
# Do not make changes to this file unless you know what you are doing - modify
# the SWIG interface file instead.

from sys import version_info as _swig_python_version_info
# Import the low-level C/C++ module
if __package__ or "." in __name__:
    from . import _invariant
else:
    import _invariant

try:
    import builtins as __builtin__
except ImportError:
    import __builtin__

def _swig_repr(self):
    try:
        strthis = "proxy of " + self.this.__repr__()
    except __builtin__.Exception:
        strthis = ""
    return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)


def _swig_setattr_nondynamic_instance_variable(set):
    def set_instance_attr(self, name, value):
        if name == "this":
            set(self, name, value)
        elif name == "thisown":
            self.this.own(value)
        elif hasattr(self, name) and isinstance(getattr(type(self), name), property):
            set(self, name, value)
        else:
            raise AttributeError("You cannot add instance attributes to %s" % self)
    return set_instance_attr


def _swig_setattr_nondynamic_class_variable(set):
    def set_class_attr(cls, name, value):
        if hasattr(cls, name) and not isinstance(getattr(cls, name), property):
            set(cls, name, value)
        else:
            raise AttributeError("You cannot add class attributes to %s" % cls)
    return set_class_attr


def _swig_add_metaclass(metaclass):
    """Class decorator for adding a metaclass to a SWIG wrapped class - a slimmed down version of six.add_metaclass"""
    def wrapper(cls):
        return metaclass(cls.__name__, cls.__bases__, cls.__dict__.copy())
    return wrapper


class _SwigNonDynamicMeta(type):
    """Meta class to enforce nondynamic attributes (no new attributes) for a class"""
    __setattr__ = _swig_setattr_nondynamic_class_variable(type.__setattr__)


class Invariant(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined")
    __repr__ = _swig_repr

    def __call__(self, ov):
        return _invariant.Invariant___call__(self, ov)
    __swig_destroy__ = _invariant.delete_Invariant

# Register Invariant in _invariant:
_invariant.Invariant_swigregister(Invariant)
class Magnitude(Invariant):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _invariant.Magnitude_swiginit(self, _invariant.new_Magnitude())
    __swig_destroy__ = _invariant.delete_Magnitude

# Register Magnitude in _invariant:
_invariant.Magnitude_swigregister(Magnitude)
class MatrixTrace(Invariant):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _invariant.MatrixTrace_swiginit(self, _invariant.new_MatrixTrace())
    __swig_destroy__ = _invariant.delete_MatrixTrace

# Register MatrixTrace in _invariant:
_invariant.MatrixTrace_swigregister(MatrixTrace)
class SecondInvariant(Invariant):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _invariant.SecondInvariant_swiginit(self, _invariant.new_SecondInvariant())
    __swig_destroy__ = _invariant.delete_SecondInvariant

# Register SecondInvariant in _invariant:
_invariant.SecondInvariant_swigregister(SecondInvariant)
class Determinant(Invariant):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _invariant.Determinant_swiginit(self, _invariant.new_Determinant())
    __swig_destroy__ = _invariant.delete_Determinant

# Register Determinant in _invariant:
_invariant.Determinant_swigregister(Determinant)
class Deviator(Invariant):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _invariant.Deviator_swiginit(self, _invariant.new_Deviator())
    __swig_destroy__ = _invariant.delete_Deviator

# Register Deviator in _invariant:
_invariant.Deviator_swigregister(Deviator)
class VonMises(Invariant):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _invariant.VonMises_swiginit(self, _invariant.new_VonMises())
    __swig_destroy__ = _invariant.delete_VonMises

# Register VonMises in _invariant:
_invariant.VonMises_swigregister(VonMises)
class Eigenvalue(Invariant):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, arg2):
        _invariant.Eigenvalue_swiginit(self, _invariant.new_Eigenvalue(arg2))
    __swig_destroy__ = _invariant.delete_Eigenvalue

# Register Eigenvalue in _invariant:
_invariant.Eigenvalue_swigregister(Eigenvalue)
# -*- python -*-


# This software was produced by NIST, an agency of the U.S. government,
# and by statute is not subject to copyright in the United States.
# Recipients of this software assume all responsibilities associated
# with its operation, modification and maintenance. However, to
# facilitate maintenance we ask that before distributing modified
# versions of this software, you first contact the authors at
# oof_manager@nist.gov. 

from ooflib.SWIG.common import switchboard
from ooflib.SWIG.engine import outputval
from ooflib.SWIG.engine import symmmatrix
from ooflib.common import cregisteredclass
from ooflib.common import debug
from ooflib.common import enum
from ooflib.common.IO import parameter
from ooflib.common.IO import xmlmenudump
from ooflib.engine import problem

cregisteredclass.registerCClass(Invariant)
Invariant.tip = "Invariants of vectors and tensors."
Invariant.discussion = xmlmenudump.loadFile(
    'DISCUSSIONS/engine/reg/invariant.xml')

# Maintain lists of which Invariants can be applied to which kinds of
# OutputVals.  The keys to the _invmap dict are OutputVal classes.
# The values are lists of Invariant Registrations.

_invmap = {}                           
def _newInvariant():
    global _invmap
    _invmap = {}
    for registration in Invariant.registry:
        for outvalclass in registration.sources:
            try:
                invlist = _invmap[outvalclass]
            except KeyError:
                invlist = []
                _invmap[outvalclass] = invlist
            invlist.append(registration)

switchboard.requestCallback(Invariant, _newInvariant)

def okInvariant(registration, outvalclass, outval):
    try:
        return (registration in _invmap[outvalclass] or
                registration in _invmap[outval])
    except KeyError:
        return 0

##########################

cregisteredclass.Registration(
    "Magnitude",
    Invariant,
    Magnitude,
    ordering=0,
    sources=[outputval.ScalarOutputVal,
             outputval.VectorOutputVal,
             symmmatrix.SymmMatrix3],
    tip="Magnitude (L2 or Frobenius norm) of a vector or tensor, absolute value of a scalar.",
    discussion=xmlmenudump.loadFile('DISCUSSIONS/engine/reg/magnitude.xml'))

cregisteredclass.Registration(
    "Trace",
    Invariant,
    MatrixTrace,
    ordering=1,
    sources=[symmmatrix.SymmMatrix3],
    tip="Trace of a symmetric tensor.",
    discussion=xmlmenudump.loadFile('DISCUSSIONS/engine/reg/trace.xml'))

cregisteredclass.Registration(
    "SecondInvariant",
    Invariant,
    SecondInvariant,
    ordering=2,
    sources=[symmmatrix.SymmMatrix3],
    tip="Second invariant of a symmetric tensor.",
    discussion=xmlmenudump.loadFile('DISCUSSIONS/engine/reg/2nd_invariant.xml'))

cregisteredclass.Registration(
    "Determinant",
    Invariant,
    Determinant,
    ordering=2,
    sources=[symmmatrix.SymmMatrix3],
    tip="Determinant of a symmetric tensor.",
    discussion=xmlmenudump.loadFile('DISCUSSIONS/engine/reg/determinant.xml'))

cregisteredclass.Registration(
    "Deviator",
    Invariant,
    Deviator,
    ordering=3,
    sources=[symmmatrix.SymmMatrix3],
    tip="Magnitude of deviatoric part of a symmetric tensor.",
    discussion=xmlmenudump.loadFile('DISCUSSIONS/engine/reg/deviator.xml'))

cregisteredclass.Registration(
    "VonMises",
    Invariant,
    VonMises,
    ordering=3.5,
    sources=[problem.Stress],
    tip="The Von Mises stress.",
    discussion=xmlmenudump.loadFile('DISCUSSIONS/engine/reg/vonmises.xml')
    )

class EigenValueRank(enum.EnumClass('Largest', 'Middle', 'Smallest')):
# If the order of the enum names is changed, then the
# EigenValueRank* typemap in invariant.swg needs to be changed
# too.
    tip = "Select an eigenvalue of a symmetric 3x3 tensor."
    discussion = xmlmenudump.loadFile(
        'DISCUSSIONS/engine/enum/eigenvaluerank.xml')

cregisteredclass.Registration(
    "Eigenvalue",
    Invariant,
    Eigenvalue,
    params=[enum.EnumParameter('which', EigenValueRank,
                               tip="Largest, middle, or smallest?")],
    ordering=4,
    sources=[symmmatrix.SymmMatrix3],
    tip="Eigenvalue of a symmetric tensor.",
    discussion=xmlmenudump.loadFile('DISCUSSIONS/engine/reg/eigenvalue.xml')
)

## TODO: Add an Invariant that returns a sorted vector of eigenvalues.
## The difficulty with this is that the whole Output machinery assumes
## that invariants are scalars.  There's no way to add an EigenValues
## Invariant and have it appear in the aggregateOutputs tree but not
## the scalarOutputs tree.  It would be possible if EigenValue(s) was
## an Output itself, and not a parameter value for the Invariant
## Output.

###############################

class InvariantParameter(parameter.RegisteredParameter):
    def __init__(self, name, value=None, default=None, tip=None):
        parameter.RegisteredParameter.__init__(self, name, Invariant,
                                               value, default, tip)
    def clone(self):
        return self.__class__(self.name, self.value, self.default, self.tip)


